@prisma-next/mongo-query-ast 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +22 -0
- package/package.json +45 -0
- package/src/aggregation-expressions.ts +482 -0
- package/src/ast-node.ts +7 -0
- package/src/commands.ts +148 -0
- package/src/exports/index.ts +97 -0
- package/src/filter-expressions.ts +210 -0
- package/src/query-plan.ts +11 -0
- package/src/raw-commands.ts +143 -0
- package/src/stages.ts +1024 -0
- package/src/visitors.ts +135 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export type { AggRecordArgs, MongoAggExpr, MongoAggSwitchBranch } from '../aggregation-expressions';
|
|
2
|
+
export {
|
|
3
|
+
isExprArray,
|
|
4
|
+
isRecordArgs,
|
|
5
|
+
MongoAggAccumulator,
|
|
6
|
+
MongoAggArrayFilter,
|
|
7
|
+
MongoAggCond,
|
|
8
|
+
MongoAggFieldRef,
|
|
9
|
+
MongoAggLet,
|
|
10
|
+
MongoAggLiteral,
|
|
11
|
+
MongoAggMap,
|
|
12
|
+
MongoAggMergeObjects,
|
|
13
|
+
MongoAggOperator,
|
|
14
|
+
MongoAggReduce,
|
|
15
|
+
MongoAggSwitch,
|
|
16
|
+
} from '../aggregation-expressions';
|
|
17
|
+
export type { AnyMongoCommand, MongoUpdateSpec } from '../commands';
|
|
18
|
+
export {
|
|
19
|
+
AggregateCommand,
|
|
20
|
+
DeleteManyCommand,
|
|
21
|
+
DeleteOneCommand,
|
|
22
|
+
FindOneAndDeleteCommand,
|
|
23
|
+
FindOneAndUpdateCommand,
|
|
24
|
+
InsertManyCommand,
|
|
25
|
+
InsertOneCommand,
|
|
26
|
+
UpdateManyCommand,
|
|
27
|
+
UpdateOneCommand,
|
|
28
|
+
} from '../commands';
|
|
29
|
+
export type { MongoFilterExpr } from '../filter-expressions';
|
|
30
|
+
export {
|
|
31
|
+
MongoAndExpr,
|
|
32
|
+
MongoExistsExpr,
|
|
33
|
+
MongoExprFilter,
|
|
34
|
+
MongoFieldFilter,
|
|
35
|
+
MongoNotExpr,
|
|
36
|
+
MongoOrExpr,
|
|
37
|
+
} from '../filter-expressions';
|
|
38
|
+
export type { MongoQueryPlan } from '../query-plan';
|
|
39
|
+
export type { RawMongoCommand } from '../raw-commands';
|
|
40
|
+
export {
|
|
41
|
+
RawAggregateCommand,
|
|
42
|
+
RawDeleteManyCommand,
|
|
43
|
+
RawDeleteOneCommand,
|
|
44
|
+
RawFindOneAndDeleteCommand,
|
|
45
|
+
RawFindOneAndUpdateCommand,
|
|
46
|
+
RawInsertManyCommand,
|
|
47
|
+
RawInsertOneCommand,
|
|
48
|
+
RawUpdateManyCommand,
|
|
49
|
+
RawUpdateOneCommand,
|
|
50
|
+
} from '../raw-commands';
|
|
51
|
+
export type {
|
|
52
|
+
MongoDensifyRange,
|
|
53
|
+
MongoFillOutput,
|
|
54
|
+
MongoGroupId,
|
|
55
|
+
MongoPipelineStage,
|
|
56
|
+
MongoProjectionValue,
|
|
57
|
+
MongoUpdatePipelineStage,
|
|
58
|
+
MongoWindowField,
|
|
59
|
+
} from '../stages';
|
|
60
|
+
export {
|
|
61
|
+
MongoAddFieldsStage,
|
|
62
|
+
MongoBucketAutoStage,
|
|
63
|
+
MongoBucketStage,
|
|
64
|
+
MongoCountStage,
|
|
65
|
+
MongoDensifyStage,
|
|
66
|
+
MongoFacetStage,
|
|
67
|
+
MongoFillStage,
|
|
68
|
+
MongoGeoNearStage,
|
|
69
|
+
MongoGraphLookupStage,
|
|
70
|
+
MongoGroupStage,
|
|
71
|
+
MongoLimitStage,
|
|
72
|
+
MongoLookupStage,
|
|
73
|
+
MongoMatchStage,
|
|
74
|
+
MongoMergeStage,
|
|
75
|
+
MongoOutStage,
|
|
76
|
+
MongoProjectStage,
|
|
77
|
+
MongoRedactStage,
|
|
78
|
+
MongoReplaceRootStage,
|
|
79
|
+
MongoSampleStage,
|
|
80
|
+
MongoSearchMetaStage,
|
|
81
|
+
MongoSearchStage,
|
|
82
|
+
MongoSetWindowFieldsStage,
|
|
83
|
+
MongoSkipStage,
|
|
84
|
+
MongoSortByCountStage,
|
|
85
|
+
MongoSortStage,
|
|
86
|
+
MongoUnionWithStage,
|
|
87
|
+
MongoUnwindStage,
|
|
88
|
+
MongoVectorSearchStage,
|
|
89
|
+
} from '../stages';
|
|
90
|
+
export type {
|
|
91
|
+
MongoAggExprRewriter,
|
|
92
|
+
MongoAggExprVisitor,
|
|
93
|
+
MongoFilterRewriter,
|
|
94
|
+
MongoFilterVisitor,
|
|
95
|
+
MongoStageRewriterContext,
|
|
96
|
+
MongoStageVisitor,
|
|
97
|
+
} from '../visitors';
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import type { MongoValue } from '@prisma-next/mongo-value';
|
|
2
|
+
import type { MongoAggExpr } from './aggregation-expressions';
|
|
3
|
+
import { MongoAstNode } from './ast-node';
|
|
4
|
+
import type { MongoFilterRewriter, MongoFilterVisitor } from './visitors';
|
|
5
|
+
|
|
6
|
+
abstract class MongoFilterExpression extends MongoAstNode {
|
|
7
|
+
abstract accept<R>(visitor: MongoFilterVisitor<R>): R;
|
|
8
|
+
abstract rewrite(rewriter: MongoFilterRewriter): MongoFilterExpr;
|
|
9
|
+
|
|
10
|
+
not(this: MongoFilterExpr): MongoNotExpr {
|
|
11
|
+
return new MongoNotExpr(this);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class MongoFieldFilter extends MongoFilterExpression {
|
|
16
|
+
readonly kind = 'field' as const;
|
|
17
|
+
readonly field: string;
|
|
18
|
+
readonly op: string;
|
|
19
|
+
readonly value: MongoValue;
|
|
20
|
+
|
|
21
|
+
constructor(field: string, op: string, value: MongoValue) {
|
|
22
|
+
super();
|
|
23
|
+
this.field = field;
|
|
24
|
+
this.op = op;
|
|
25
|
+
this.value = value;
|
|
26
|
+
this.freeze();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static of(field: string, op: string, value: MongoValue): MongoFieldFilter {
|
|
30
|
+
return new MongoFieldFilter(field, op, value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static eq(field: string, value: MongoValue): MongoFieldFilter {
|
|
34
|
+
return new MongoFieldFilter(field, '$eq', value);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static neq(field: string, value: MongoValue): MongoFieldFilter {
|
|
38
|
+
return new MongoFieldFilter(field, '$ne', value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static gt(field: string, value: MongoValue): MongoFieldFilter {
|
|
42
|
+
return new MongoFieldFilter(field, '$gt', value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static lt(field: string, value: MongoValue): MongoFieldFilter {
|
|
46
|
+
return new MongoFieldFilter(field, '$lt', value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static gte(field: string, value: MongoValue): MongoFieldFilter {
|
|
50
|
+
return new MongoFieldFilter(field, '$gte', value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static lte(field: string, value: MongoValue): MongoFieldFilter {
|
|
54
|
+
return new MongoFieldFilter(field, '$lte', value);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static in(field: string, values: ReadonlyArray<MongoValue>): MongoFieldFilter {
|
|
58
|
+
return new MongoFieldFilter(field, '$in', values);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static isNull(field: string): MongoFieldFilter {
|
|
62
|
+
return new MongoFieldFilter(field, '$eq', null);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static isNotNull(field: string): MongoFieldFilter {
|
|
66
|
+
return new MongoFieldFilter(field, '$ne', null);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
accept<R>(visitor: MongoFilterVisitor<R>): R {
|
|
70
|
+
return visitor.field(this);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
rewrite(rewriter: MongoFilterRewriter): MongoFilterExpr {
|
|
74
|
+
return rewriter.field ? rewriter.field(this) : this;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export class MongoAndExpr extends MongoFilterExpression {
|
|
79
|
+
readonly kind = 'and' as const;
|
|
80
|
+
readonly exprs: ReadonlyArray<MongoFilterExpr>;
|
|
81
|
+
|
|
82
|
+
constructor(exprs: ReadonlyArray<MongoFilterExpr>) {
|
|
83
|
+
super();
|
|
84
|
+
if (exprs.length === 0) {
|
|
85
|
+
throw new Error('$and requires at least one expression');
|
|
86
|
+
}
|
|
87
|
+
this.exprs = Object.freeze([...exprs]);
|
|
88
|
+
this.freeze();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static of(exprs: ReadonlyArray<MongoFilterExpr>): MongoAndExpr {
|
|
92
|
+
return new MongoAndExpr(exprs);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
accept<R>(visitor: MongoFilterVisitor<R>): R {
|
|
96
|
+
return visitor.and(this);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
rewrite(rewriter: MongoFilterRewriter): MongoFilterExpr {
|
|
100
|
+
const rewritten = new MongoAndExpr(this.exprs.map((e) => e.rewrite(rewriter)));
|
|
101
|
+
return rewriter.and ? rewriter.and(rewritten) : rewritten;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export class MongoOrExpr extends MongoFilterExpression {
|
|
106
|
+
readonly kind = 'or' as const;
|
|
107
|
+
readonly exprs: ReadonlyArray<MongoFilterExpr>;
|
|
108
|
+
|
|
109
|
+
constructor(exprs: ReadonlyArray<MongoFilterExpr>) {
|
|
110
|
+
super();
|
|
111
|
+
if (exprs.length === 0) {
|
|
112
|
+
throw new Error('$or requires at least one expression');
|
|
113
|
+
}
|
|
114
|
+
this.exprs = Object.freeze([...exprs]);
|
|
115
|
+
this.freeze();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static of(exprs: ReadonlyArray<MongoFilterExpr>): MongoOrExpr {
|
|
119
|
+
return new MongoOrExpr(exprs);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
accept<R>(visitor: MongoFilterVisitor<R>): R {
|
|
123
|
+
return visitor.or(this);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
rewrite(rewriter: MongoFilterRewriter): MongoFilterExpr {
|
|
127
|
+
const rewritten = new MongoOrExpr(this.exprs.map((e) => e.rewrite(rewriter)));
|
|
128
|
+
return rewriter.or ? rewriter.or(rewritten) : rewritten;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export class MongoNotExpr extends MongoFilterExpression {
|
|
133
|
+
readonly kind = 'not' as const;
|
|
134
|
+
readonly expr: MongoFilterExpr;
|
|
135
|
+
|
|
136
|
+
constructor(expr: MongoFilterExpr) {
|
|
137
|
+
super();
|
|
138
|
+
this.expr = expr;
|
|
139
|
+
this.freeze();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
accept<R>(visitor: MongoFilterVisitor<R>): R {
|
|
143
|
+
return visitor.not(this);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
rewrite(rewriter: MongoFilterRewriter): MongoFilterExpr {
|
|
147
|
+
const rewritten = new MongoNotExpr(this.expr.rewrite(rewriter));
|
|
148
|
+
return rewriter.not ? rewriter.not(rewritten) : rewritten;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export class MongoExistsExpr extends MongoFilterExpression {
|
|
153
|
+
readonly kind = 'exists' as const;
|
|
154
|
+
readonly field: string;
|
|
155
|
+
readonly exists: boolean;
|
|
156
|
+
|
|
157
|
+
constructor(field: string, exists: boolean) {
|
|
158
|
+
super();
|
|
159
|
+
this.field = field;
|
|
160
|
+
this.exists = exists;
|
|
161
|
+
this.freeze();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static exists(field: string): MongoExistsExpr {
|
|
165
|
+
return new MongoExistsExpr(field, true);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static notExists(field: string): MongoExistsExpr {
|
|
169
|
+
return new MongoExistsExpr(field, false);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
accept<R>(visitor: MongoFilterVisitor<R>): R {
|
|
173
|
+
return visitor.exists(this);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
rewrite(rewriter: MongoFilterRewriter): MongoFilterExpr {
|
|
177
|
+
return rewriter.exists ? rewriter.exists(this) : this;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export class MongoExprFilter extends MongoFilterExpression {
|
|
182
|
+
readonly kind = 'expr' as const;
|
|
183
|
+
readonly aggExpr: MongoAggExpr;
|
|
184
|
+
|
|
185
|
+
constructor(aggExpr: MongoAggExpr) {
|
|
186
|
+
super();
|
|
187
|
+
this.aggExpr = aggExpr;
|
|
188
|
+
this.freeze();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static of(aggExpr: MongoAggExpr): MongoExprFilter {
|
|
192
|
+
return new MongoExprFilter(aggExpr);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
accept<R>(visitor: MongoFilterVisitor<R>): R {
|
|
196
|
+
return visitor.expr(this);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
rewrite(rewriter: MongoFilterRewriter): MongoFilterExpr {
|
|
200
|
+
return rewriter.expr ? rewriter.expr(this) : this;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export type MongoFilterExpr =
|
|
205
|
+
| MongoFieldFilter
|
|
206
|
+
| MongoAndExpr
|
|
207
|
+
| MongoOrExpr
|
|
208
|
+
| MongoNotExpr
|
|
209
|
+
| MongoExistsExpr
|
|
210
|
+
| MongoExprFilter;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PlanMeta } from '@prisma-next/contract/types';
|
|
2
|
+
import type { AnyMongoCommand } from './commands';
|
|
3
|
+
|
|
4
|
+
declare const __mongoQueryPlanRow: unique symbol;
|
|
5
|
+
|
|
6
|
+
export interface MongoQueryPlan<Row = unknown> {
|
|
7
|
+
readonly collection: string;
|
|
8
|
+
readonly command: AnyMongoCommand;
|
|
9
|
+
readonly meta: PlanMeta;
|
|
10
|
+
readonly [__mongoQueryPlanRow]?: Row;
|
|
11
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { Document } from '@prisma-next/mongo-value';
|
|
2
|
+
import { MongoAstNode } from './ast-node';
|
|
3
|
+
|
|
4
|
+
export class RawAggregateCommand extends MongoAstNode {
|
|
5
|
+
readonly kind = 'rawAggregate' as const;
|
|
6
|
+
readonly collection: string;
|
|
7
|
+
readonly pipeline: ReadonlyArray<Document>;
|
|
8
|
+
|
|
9
|
+
constructor(collection: string, pipeline: ReadonlyArray<Document>) {
|
|
10
|
+
super();
|
|
11
|
+
this.collection = collection;
|
|
12
|
+
this.pipeline = pipeline;
|
|
13
|
+
this.freeze();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class RawInsertOneCommand extends MongoAstNode {
|
|
18
|
+
readonly kind = 'rawInsertOne' as const;
|
|
19
|
+
readonly collection: string;
|
|
20
|
+
readonly document: Document;
|
|
21
|
+
|
|
22
|
+
constructor(collection: string, document: Document) {
|
|
23
|
+
super();
|
|
24
|
+
this.collection = collection;
|
|
25
|
+
this.document = document;
|
|
26
|
+
this.freeze();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class RawInsertManyCommand extends MongoAstNode {
|
|
31
|
+
readonly kind = 'rawInsertMany' as const;
|
|
32
|
+
readonly collection: string;
|
|
33
|
+
readonly documents: ReadonlyArray<Document>;
|
|
34
|
+
|
|
35
|
+
constructor(collection: string, documents: ReadonlyArray<Document>) {
|
|
36
|
+
super();
|
|
37
|
+
this.collection = collection;
|
|
38
|
+
this.documents = documents;
|
|
39
|
+
this.freeze();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class RawUpdateOneCommand extends MongoAstNode {
|
|
44
|
+
readonly kind = 'rawUpdateOne' as const;
|
|
45
|
+
readonly collection: string;
|
|
46
|
+
readonly filter: Document;
|
|
47
|
+
readonly update: Document | ReadonlyArray<Document>;
|
|
48
|
+
|
|
49
|
+
constructor(collection: string, filter: Document, update: Document | ReadonlyArray<Document>) {
|
|
50
|
+
super();
|
|
51
|
+
this.collection = collection;
|
|
52
|
+
this.filter = filter;
|
|
53
|
+
this.update = update;
|
|
54
|
+
this.freeze();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export class RawUpdateManyCommand extends MongoAstNode {
|
|
59
|
+
readonly kind = 'rawUpdateMany' as const;
|
|
60
|
+
readonly collection: string;
|
|
61
|
+
readonly filter: Document;
|
|
62
|
+
readonly update: Document | ReadonlyArray<Document>;
|
|
63
|
+
|
|
64
|
+
constructor(collection: string, filter: Document, update: Document | ReadonlyArray<Document>) {
|
|
65
|
+
super();
|
|
66
|
+
this.collection = collection;
|
|
67
|
+
this.filter = filter;
|
|
68
|
+
this.update = update;
|
|
69
|
+
this.freeze();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class RawDeleteOneCommand extends MongoAstNode {
|
|
74
|
+
readonly kind = 'rawDeleteOne' as const;
|
|
75
|
+
readonly collection: string;
|
|
76
|
+
readonly filter: Document;
|
|
77
|
+
|
|
78
|
+
constructor(collection: string, filter: Document) {
|
|
79
|
+
super();
|
|
80
|
+
this.collection = collection;
|
|
81
|
+
this.filter = filter;
|
|
82
|
+
this.freeze();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export class RawDeleteManyCommand extends MongoAstNode {
|
|
87
|
+
readonly kind = 'rawDeleteMany' as const;
|
|
88
|
+
readonly collection: string;
|
|
89
|
+
readonly filter: Document;
|
|
90
|
+
|
|
91
|
+
constructor(collection: string, filter: Document) {
|
|
92
|
+
super();
|
|
93
|
+
this.collection = collection;
|
|
94
|
+
this.filter = filter;
|
|
95
|
+
this.freeze();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export class RawFindOneAndUpdateCommand extends MongoAstNode {
|
|
100
|
+
readonly kind = 'rawFindOneAndUpdate' as const;
|
|
101
|
+
readonly collection: string;
|
|
102
|
+
readonly filter: Document;
|
|
103
|
+
readonly update: Document | ReadonlyArray<Document>;
|
|
104
|
+
readonly upsert: boolean;
|
|
105
|
+
|
|
106
|
+
constructor(
|
|
107
|
+
collection: string,
|
|
108
|
+
filter: Document,
|
|
109
|
+
update: Document | ReadonlyArray<Document>,
|
|
110
|
+
upsert: boolean,
|
|
111
|
+
) {
|
|
112
|
+
super();
|
|
113
|
+
this.collection = collection;
|
|
114
|
+
this.filter = filter;
|
|
115
|
+
this.update = update;
|
|
116
|
+
this.upsert = upsert;
|
|
117
|
+
this.freeze();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export class RawFindOneAndDeleteCommand extends MongoAstNode {
|
|
122
|
+
readonly kind = 'rawFindOneAndDelete' as const;
|
|
123
|
+
readonly collection: string;
|
|
124
|
+
readonly filter: Document;
|
|
125
|
+
|
|
126
|
+
constructor(collection: string, filter: Document) {
|
|
127
|
+
super();
|
|
128
|
+
this.collection = collection;
|
|
129
|
+
this.filter = filter;
|
|
130
|
+
this.freeze();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type RawMongoCommand =
|
|
135
|
+
| RawAggregateCommand
|
|
136
|
+
| RawInsertOneCommand
|
|
137
|
+
| RawInsertManyCommand
|
|
138
|
+
| RawUpdateOneCommand
|
|
139
|
+
| RawUpdateManyCommand
|
|
140
|
+
| RawDeleteOneCommand
|
|
141
|
+
| RawDeleteManyCommand
|
|
142
|
+
| RawFindOneAndUpdateCommand
|
|
143
|
+
| RawFindOneAndDeleteCommand;
|