mythix-orm 1.10.2 → 1.11.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.
@@ -3,11 +3,128 @@
3
3
  const Nife = require('nife');
4
4
  const ProxyClass = require('../proxy-class');
5
5
  const QueryEngineBase = require('./query-engine-base');
6
+ const QueryUtils = require('../utils/query-utils');
6
7
  const {
7
8
  LiteralBase,
8
9
  DistinctLiteral,
9
10
  } = require('../connection/literals');
10
11
 
12
+ function applyOrderClause(extraData, ...args) {
13
+ let entities = Nife.arrayFlatten(args);
14
+
15
+ entities = Nife.toArray(entities).map((value) => {
16
+ if (value == null)
17
+ return;
18
+
19
+ // Pass literals directly through
20
+ if (LiteralBase.isLiteral(value))
21
+ return value;
22
+
23
+ // Is the projection a field?
24
+ if (value.Model && value.fieldName)
25
+ return `${value.Model.getModelName()}:${value.fieldName}`;
26
+
27
+ if (!Nife.instanceOf(value, 'string'))
28
+ throw new Error('QueryEngine::ModelScope::ORDER: Invalid value provided. All values provided must be strings, fields, or literals. If you want to change the sort order of a given column, add "+" (ASC) or "-" (DESC) to be beginning of the field name. Example: .ORDER("+createdAt"), or .ORDER([ "-name", "+createdAt" ]).');
29
+
30
+ return value;
31
+ }).filter(Boolean);
32
+
33
+ let context = this.getOperationContext();
34
+ let order = this.margeFields(
35
+ context.order,
36
+ entities,
37
+ extraData,
38
+ { isOrderBy: true },
39
+ );
40
+
41
+ this._pushOperationOntoStack({
42
+ control: true,
43
+ operator: 'ORDER',
44
+ queryProp: 'ORDER',
45
+ value: entities,
46
+ order,
47
+ });
48
+
49
+ return this._fetchScope('model');
50
+ }
51
+
52
+ function wrapOrderClause(func) {
53
+ const applyQueryOrder = (_order, replace) => {
54
+ let query = this;
55
+ let order = Nife.toArray(_order).filter(Boolean);
56
+
57
+ let asc = order.filter((thisOrder) => {
58
+ if (!Nife.instanceOf(thisOrder, 'string'))
59
+ return true;
60
+
61
+ if (thisOrder.charAt(0) === '-')
62
+ return false;
63
+
64
+ return true;
65
+ });
66
+
67
+ let desc = order.filter((thisOrder) => {
68
+ if (!Nife.instanceOf(thisOrder, 'string'))
69
+ return false;
70
+
71
+ if (thisOrder.charAt(0) !== '-')
72
+ return false;
73
+
74
+ return true;
75
+ });
76
+
77
+ if (Nife.isNotEmpty(asc)) {
78
+ asc = asc.map((thisOrder) => {
79
+ if (!Nife.instanceOf(thisOrder, 'string'))
80
+ return thisOrder;
81
+
82
+ return thisOrder.replace(/^\+/, '');
83
+ });
84
+
85
+ // eslint-disable-next-line new-cap
86
+ query = (replace) ? ASC(asc) : ASC('+', asc);
87
+ }
88
+
89
+ if (Nife.isNotEmpty(desc)) {
90
+ desc = desc.map((thisOrder) => {
91
+ if (!Nife.instanceOf(thisOrder, 'string'))
92
+ return thisOrder;
93
+
94
+ return thisOrder.replace(/^-/, '');
95
+ });
96
+
97
+ // eslint-disable-next-line new-cap
98
+ query = (replace) ? DESC(desc) : DESC('+', desc);
99
+ }
100
+
101
+ return query;
102
+ };
103
+
104
+ const DESC = (...args) => {
105
+ return applyOrderClause.call(this, { direction: '-' }, ...args);
106
+ };
107
+
108
+ const ASC = (...args) => {
109
+ return applyOrderClause.call(this, { direction: '+' }, ...args);
110
+ };
111
+
112
+ const ADD = (...args) => {
113
+ return applyQueryOrder(args, false);
114
+ };
115
+
116
+ const REPLACE = (...args) => {
117
+ return applyQueryOrder(args, true);
118
+ };
119
+
120
+ func.DESC = DESC;
121
+ func.ASC = ASC;
122
+ func.ADD = ADD;
123
+ func.REPLACE = REPLACE;
124
+
125
+ return func;
126
+ }
127
+
11
128
  class ModelScope extends QueryEngineBase {
12
129
  _getField(fieldName) {
13
130
  let Model = this.currentContext.Model;
@@ -46,18 +163,22 @@ class ModelScope extends QueryEngineBase {
46
163
  return this.currentContext.queryEngineScope.toString(...args);
47
164
  }
48
165
 
166
+ margeFields(currentFields, incomingFields, extraData, options) {
167
+ return QueryUtils.margeFields(this, currentFields, incomingFields, extraData, options);
168
+ }
169
+
49
170
  NOT = ProxyClass.autoCall(function() {
50
- this._pushOperationOntoStack({ logical: true, operator: 'NOT', not: !this.currentContext.not });
171
+ this._pushOperationOntoStack({ logical: true, operator: 'NOT', queryProp: 'NOT', not: !this.currentContext.not });
51
172
  return this._fetchScope('model');
52
173
  });
53
174
 
54
175
  AND = ProxyClass.autoCall(function(value) {
55
- this._pushOperationOntoStack({ logical: true, operator: 'AND', and: true, or: false, not: false, value });
176
+ this._pushOperationOntoStack({ logical: true, operator: 'AND', queryProp: 'AND', and: true, or: false, not: false, value });
56
177
  return this._fetchScope('model');
57
178
  });
58
179
 
59
180
  OR = ProxyClass.autoCall(function(value) {
60
- this._pushOperationOntoStack({ logical: true, operator: 'OR', and: false, or: true, not: false, value });
181
+ this._pushOperationOntoStack({ logical: true, operator: 'OR', queryProp: 'OR', and: false, or: true, not: false, value });
61
182
  return this._fetchScope('model');
62
183
  });
63
184
 
@@ -67,7 +188,7 @@ class ModelScope extends QueryEngineBase {
67
188
  throw new Error('QueryEngine::ModelScope::LIMIT: Value provided must be a valid positive number, or Infinity.');
68
189
 
69
190
  value = Math.round(value);
70
- this._pushOperationOntoStack({ control: true, operator: 'LIMIT', value, limit: value });
191
+ this._pushOperationOntoStack({ control: true, operator: 'LIMIT', queryProp: 'LIMIT', value, limit: value });
71
192
 
72
193
  return this._fetchScope('model');
73
194
  }
@@ -78,32 +199,93 @@ class ModelScope extends QueryEngineBase {
78
199
  throw new Error('QueryEngine::ModelScope::OFFSET: Value provided must be a valid positive number.');
79
200
 
80
201
  value = Math.round(value);
81
- this._pushOperationOntoStack({ control: true, operator: 'OFFSET', value, offset: value });
202
+ this._pushOperationOntoStack({ control: true, operator: 'OFFSET', queryProp: 'OFFSET', value, offset: value });
82
203
 
83
204
  return this._fetchScope('model');
84
205
  }
85
206
 
86
- ORDER(...args) {
87
- let values = Nife.arrayFlatten(args);
207
+ ORDER = wrapOrderClause.call(this, (...args) => {
208
+ return applyOrderClause.call(this, { direction: '+' }, ...args);
209
+ });
88
210
 
89
- values = Nife.toArray(values).filter((value) => {
211
+ GROUP_BY(...args) {
212
+ let entities = Nife.arrayFlatten(args);
213
+
214
+ entities = Nife.toArray(entities).map((value) => {
90
215
  if (value == null)
91
- return false;
216
+ return;
217
+
218
+ // Pass literals directly through
219
+ if (LiteralBase.isLiteral(value))
220
+ return value;
221
+
222
+ // Is the projection a field?
223
+ if (value.Model && value.fieldName)
224
+ return `${value.Model.getModelName()}:${value.fieldName}`;
92
225
 
93
226
  if (!Nife.instanceOf(value, 'string'))
94
- throw new Error('QueryEngine::ModelScope::ORDER: Invalid value provided. All values provided must be strings. If you want to change the sort order of a given column, add "+" (ASC) or "-" (DESC) to be beginning of the field name. Example: .ORDER("+createdAt"), or .ORDER([ "-name", "+createdAt" ]).');
227
+ throw new Error('QueryEngine::ModelScope::GROUP_BY: Invalid value provided. All values provided must be strings, fields, or literals. If you want to change the sort order of a given column, add "+" (ASC) or "-" (DESC) to be beginning of the field name. Example: .ORDER("+createdAt"), or .ORDER([ "-name", "+createdAt" ]).');
95
228
 
96
- return true;
229
+ return value;
230
+ }).filter(Boolean);
231
+
232
+ let context = this.getOperationContext();
233
+ let groupBy = this.margeFields(
234
+ context.groupBy,
235
+ entities,
236
+ {},
237
+ { isGroupBy: true },
238
+ );
239
+
240
+ this._pushOperationOntoStack({
241
+ control: true,
242
+ operator: 'GROUP_BY',
243
+ queryProp: 'GROUP_BY',
244
+ value: entities,
245
+ groupBy,
246
+ });
247
+
248
+ return this._fetchScope('model');
249
+ }
250
+
251
+ HAVING(query) {
252
+ this._pushOperationOntoStack({ control: true, operator: 'HAVING', queryProp: 'HAVING', value: query, having: query });
253
+ return this._fetchScope('model');
254
+ }
255
+
256
+ EXISTS(_query) {
257
+ let query = _query;
258
+ let queryContext = (QueryEngineBase.isQuery(query)) ? query.getOperationContext() : null;
259
+ if (!queryContext || !queryContext.hasCondition)
260
+ throw new Error('QueryEngine::ModelScope::EXISTS: Provided value must be a query with conditions.');
261
+
262
+ if (!queryContext.projection) {
263
+ let Model = queryContext.Model;
264
+ let pkField = Model.getPrimaryKeyField();
265
+
266
+ if (pkField)
267
+ query = query.clone().PROJECT(pkField);
268
+ else
269
+ throw new Error('QueryEngine::ModelScope::EXISTS: Provided query must have only a single field projected.');
270
+ }
271
+
272
+ this._pushOperationOntoStack({
273
+ condition: true,
274
+ operator: 'EXISTS',
275
+ inverseOperator: 'NOT EXISTS',
276
+ queryProp: 'EXISTS',
277
+ value: query,
278
+ having: query,
279
+ hasCondition: true,
97
280
  });
98
281
 
99
- this._pushOperationOntoStack({ control: true, operator: 'ORDER', value: values, order: values });
100
282
  return this._fetchScope('model');
101
283
  }
102
284
 
103
285
  PROJECT(...args) {
104
- let values = Nife.arrayFlatten(args);
286
+ let entities = Nife.arrayFlatten(args);
105
287
 
106
- values = Nife.toArray(values).map((value) => {
288
+ entities = Nife.toArray(entities).map((value) => {
107
289
  if (value == null)
108
290
  return;
109
291
 
@@ -119,63 +301,78 @@ class ModelScope extends QueryEngineBase {
119
301
  if (value.Model && value.fieldName)
120
302
  return value;
121
303
 
122
- if (!Nife.instanceOf(value, 'string'))
123
- throw new Error('QueryEngine::ModelScope::PROJECT: Invalid value provided. All values provided must be strings.');
304
+ if (!Nife.instanceOf(value, 'string')) {
305
+ console.log(entities);
306
+ throw new Error(`QueryEngine::ModelScope::PROJECT: Invalid value provided [${value.toString()}]. All values provided must be strings.`);
307
+ }
124
308
 
125
309
  return value;
126
310
  }).filter(Boolean);
127
311
 
128
- this._pushOperationOntoStack({ control: true, operator: 'PROJECT', value: values });
312
+ let context = this.getOperationContext();
313
+ let projection = this.margeFields(
314
+ context.projection,
315
+ entities,
316
+ {},
317
+ { isProjection: true },
318
+ );
319
+
320
+ this._pushOperationOntoStack({
321
+ control: true,
322
+ operator: 'PROJECT',
323
+ queryProp: 'PROJECT',
324
+ value: entities,
325
+ projection,
326
+ });
327
+
129
328
  return this._fetchScope('model');
130
329
  }
131
330
 
132
331
  DISTINCT = ProxyClass.autoCall(function(fullyQualifiedName) {
133
332
  let currentQuery = this;
134
333
  let distinctValue = fullyQualifiedName;
334
+ let context = this.getOperationContext();
135
335
 
136
336
  if (arguments.length === 0) {
137
- let context = this.getOperationContext();
138
337
  let rootModel = context.rootModel;
139
- if (!rootModel)
140
- throw new Error(`${this.constructor.name}::DISTINCT: Attempted to apply DISTINCT to the root model of the query, but no root model was found.`);
141
-
142
- let pkFieldName = rootModel.getPrimaryKeyFieldName();
143
- if (!pkFieldName)
144
- throw new Error(`${this.constructor.name}::DISTINCT: Attempted to apply DISTINCT to the root model of the query, but the root model has no primary key. Try directly specifying the DISTINCT field instead.`);
145
-
146
- distinctValue = new DistinctLiteral(`${rootModel.getModelName()}:${pkFieldName}`);
147
- currentQuery = this.PROJECT(`-${rootModel.getModelName()}:${pkFieldName}`);
338
+ if (rootModel) {
339
+ let pkFieldName = rootModel.getPrimaryKeyFieldName();
340
+ if (pkFieldName)
341
+ distinctValue = new DistinctLiteral(`${rootModel.getModelName()}:${pkFieldName}`);
342
+ }
343
+
344
+ if (!distinctValue)
345
+ distinctValue = new DistinctLiteral();
148
346
  } else if (fullyQualifiedName) {
149
347
  distinctValue = new DistinctLiteral(fullyQualifiedName);
150
- currentQuery = this.PROJECT(`-${fullyQualifiedName}`);
151
348
  }
152
349
 
153
- currentQuery._pushOperationOntoStack({ control: true, operator: 'DISTINCT', value: distinctValue, distinct: distinctValue });
350
+ currentQuery._pushOperationOntoStack({ sqlFunc: true, operator: 'DISTINCT', queryProp: 'DISTINCT', value: distinctValue, distinct: distinctValue });
154
351
  return this._fetchScope('model');
155
352
  });
156
353
 
157
354
  INNER_JOIN = ProxyClass.autoCall(function() {
158
- this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'inner', joinType: 'inner', joinOuter: false });
355
+ this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'INNER_JOIN', value: 'inner', joinType: 'inner', joinOuter: false });
159
356
  return this._fetchScope('model');
160
357
  });
161
358
 
162
359
  LEFT_JOIN = ProxyClass.autoCall(function(outerJoin) {
163
- this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'left', joinType: 'left', joinOuter: !!outerJoin });
360
+ this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'LEFT_JOIN', value: 'left', joinType: 'left', joinOuter: !!outerJoin });
164
361
  return this._fetchScope('model');
165
362
  });
166
363
 
167
364
  RIGHT_JOIN = ProxyClass.autoCall(function(outerJoin) {
168
- this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'right', joinType: 'right', joinOuter: !!outerJoin });
365
+ this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'RIGHT_JOIN', value: 'right', joinType: 'right', joinOuter: !!outerJoin });
169
366
  return this._fetchScope('model');
170
367
  });
171
368
 
172
369
  FULL_JOIN = ProxyClass.autoCall(function(outerJoin) {
173
- this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'full', joinType: 'full', joinOuter: !!outerJoin });
370
+ this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'FULL_JOIN', value: 'full', joinType: 'full', joinOuter: !!outerJoin });
174
371
  return this._fetchScope('model');
175
372
  });
176
373
 
177
374
  CROSS_JOIN = ProxyClass.autoCall(function() {
178
- this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'cross', joinType: 'cross', joinOuter: false });
375
+ this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'CROSS_JOIN', value: 'cross', joinType: 'cross', joinOuter: false });
179
376
  return this._fetchScope('model');
180
377
  });
181
378
 
@@ -183,7 +380,7 @@ class ModelScope extends QueryEngineBase {
183
380
  if (!(Nife.instanceOf(type, 'string') || LiteralBase.isLiteral(type)))
184
381
  throw new Error('QueryEngine::ModelScope::JOIN: Invalid value provided. Value must be a valid string or Literal specifying JOIN type.');
185
382
 
186
- this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: type, joinType: type, joinOuter: false });
383
+ this._pushOperationOntoStack({ join: true, operator: 'JOIN', queryProp: 'JOIN', value: type, joinType: type, joinOuter: false });
187
384
  return this._fetchScope('model');
188
385
  }
189
386
  }
@@ -13,8 +13,8 @@ class QueryEngineBase extends ProxyClass {
13
13
  return uuid++;
14
14
  }
15
15
 
16
- static isQueryContext(value) {
17
- return !!(value && value.isQueryContext);
16
+ static isQueryOperationContext(value) {
17
+ return !!(value && value.isQueryOperationContext);
18
18
  }
19
19
 
20
20
  static isQuery(value) {
@@ -33,7 +33,7 @@ class QueryEngineBase extends ProxyClass {
33
33
  return false;
34
34
  }
35
35
 
36
- static queryContextType(queryContext) {
36
+ static queryOperationInfo(queryContext) {
37
37
  let contextParams = {
38
38
  hasCondition: false,
39
39
  hasField: false,
@@ -124,8 +124,10 @@ class QueryEngineBase extends ProxyClass {
124
124
  let modelName = Model.getModelName();
125
125
  let context = this.currentContext;
126
126
  let extra = {};
127
+ let isFirst = !context.rootModel;
128
+ let connection = this.getConnection();
127
129
 
128
- if (!context.rootModel) {
130
+ if (isFirst) {
129
131
  extra.rootModelName = modelName;
130
132
  extra.rootModel = Model;
131
133
  }
@@ -141,13 +143,10 @@ class QueryEngineBase extends ProxyClass {
141
143
  throw new Error(`QueryEngine: Model "${Model.getModelName()}" is on a different connection dialect than the current query dialect of "${context.dialect}". You can not match different connection dialects in the same query.`);
142
144
  }
143
145
 
144
- if (!dialect) {
145
- let connection = this.getConnection();
146
- if (connection)
147
- dialect = connection.dialect;
148
- }
146
+ if (!dialect && connection)
147
+ dialect = connection.dialect;
149
148
 
150
- let newContext = this._inheritContext(context, 'model', { operator: 'MODEL', Model, modelName, dialect }, extra);
149
+ let newContext = this._inheritContext(context, 'model', { operator: 'MODEL', queryProp: 'Model', Model, modelName, dialect, value: modelName }, extra);
151
150
  let newScope = new ModelScopeClass(newContext);
152
151
 
153
152
  // We shouldn't add this scope if this is
@@ -155,6 +154,9 @@ class QueryEngineBase extends ProxyClass {
155
154
  if (context.Model !== Model)
156
155
  context.operationStack.push(newContext);
157
156
 
157
+ if (isFirst)
158
+ newScope = newScope.PROJECT(Model);
159
+
158
160
  // But we always need to return the scope
159
161
  // for the proxy to work properly
160
162
  return newScope;
@@ -171,7 +173,7 @@ class QueryEngineBase extends ProxyClass {
171
173
  extra.rootField = Field;
172
174
  }
173
175
 
174
- let newContext = this._inheritContext(context, 'field', { operator: 'FIELD', fieldName, Field }, extra);
176
+ let newContext = this._inheritContext(context, 'field', { operator: 'FIELD', queryProp: 'Field', fieldName, Field, value: fieldName }, extra);
175
177
  let newScope = new FieldScopeClass(newContext);
176
178
 
177
179
  // We shouldn't add this scope if this is
@@ -223,7 +225,7 @@ class QueryEngineBase extends ProxyClass {
223
225
  let currentContext = operationStack[operationStack.length - 1];
224
226
  return currentContext || context;
225
227
  },
226
- set: () => {},
228
+ set: () => {},
227
229
  },
228
230
  });
229
231
  }
@@ -289,7 +291,6 @@ class QueryEngineBase extends ProxyClass {
289
291
  else
290
292
  console.log(`${operator} -> ${queryPart.value}`);
291
293
  }
292
-
293
294
  }
294
295
 
295
296
  _pushOperationOntoStack(queryPart, _context) {
@@ -409,6 +410,38 @@ class QueryEngineBase extends ProxyClass {
409
410
  let checkContextKeys = _checkContextKeys || [ 'value' ];
410
411
  walkQueries(this, null, null, 0);
411
412
  }
413
+
414
+ getAllModelsUsedInQuery() {
415
+ let Models = new Set();
416
+ let query = this.getOperationStack();
417
+
418
+ for (let i = 0, il = query.length; i < il; i++) {
419
+ let queryPart = query[i];
420
+
421
+ if (Object.prototype.hasOwnProperty.call(queryPart, 'operator') && queryPart.operator === 'MODEL') {
422
+ let Model = queryPart.Model;
423
+ Models.add(Model);
424
+ } else if (Object.prototype.hasOwnProperty.call(queryPart, 'condition') && queryPart.condition === true) {
425
+ let operatorValue = queryPart.value;
426
+ if (!QueryEngineBase.isQuery(operatorValue) || operatorValue.queryHasConditions())
427
+ continue;
428
+
429
+ let SubModels = operatorValue.getAllModelsUsedInQuery();
430
+ for (let j = 0, jl = SubModels.length; j < jl; j++) {
431
+ let Model = SubModels[j];
432
+ Models.add(Model);
433
+ }
434
+ }
435
+ }
436
+
437
+ let allModels = Array.from(Models.values());
438
+ return allModels;
439
+ }
440
+
441
+ isModelUsedInQuery(Model) {
442
+ let allModels = this.getAllModelsUsedInQuery();
443
+ return (allModels.indexOf(Model) >= 0);
444
+ }
412
445
  }
413
446
 
414
447
  module.exports = QueryEngineBase;
@@ -19,9 +19,9 @@ export declare interface CallableInterface {
19
19
  export declare class QueryEngine<T = ConnectionBase> {
20
20
  // QueryEngineBase
21
21
  static generateID(): number;
22
- static isQueryContext(value: any): boolean;
22
+ static isQueryOperationContext(value: any): boolean;
23
23
  static isQuery(value: any): boolean;
24
- static queryContextType(queryContext: GenericObject): { hasCondition: boolean; hasField: boolean; hasModel: boolean; };
24
+ static queryOperationInfo(queryContext: GenericObject): { hasCondition: boolean; hasField: boolean; hasModel: boolean; };
25
25
 
26
26
  public getModelScopeClass(): QueryEngine;
27
27
  public getFieldScopeClass(): QueryEngine;
@@ -48,6 +48,7 @@ export declare class QueryEngine<T = ConnectionBase> {
48
48
  public filter(callback: (operation: GenericObject, index: number, operations: Array<GenericObject>, query: QueryEngine) => GenericObject): QueryEngine;
49
49
  public map(callback: (operation: GenericObject, index: number, operations: Array<GenericObject>, query: QueryEngine) => GenericObject): QueryEngine;
50
50
  public walk(callback: (query: QueryEngine, parent: GenericObject | null, contextKey: string, depth: number) => GenericObject, checkContextKeys?: Array<string>): void;
51
+ public getAllModelsUsedInQuery(): Array<ModelClass>;
51
52
 
52
53
  // QueryEngine
53
54
  public getModelScopeClass(): QueryEngineClass;
@@ -78,8 +79,21 @@ export declare class QueryEngine<T = ConnectionBase> {
78
79
  public Field(fieldName: string): QueryEngine;
79
80
  public LIMIT(value: number): QueryEngine;
80
81
  public OFFSET(value: number): QueryEngine;
81
- public ORDER(...args: Array<string | Array<string>>): QueryEngine;
82
- public PROJECT(...args: Array<string | ModelClass | LiteralBase | Field>): QueryEngine;
82
+ public GROUP_BY(...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>): QueryEngine;
83
+ public HAVING(query: QueryEngine): QueryEngine;
84
+ public EXISTS(query: QueryEngine): QueryEngine;
85
+ public PROJECT(...args: Array<string | ModelClass | LiteralBase | Field | Array<string | ModelClass | LiteralBase | Field>>): QueryEngine;
86
+
87
+ declare public ORDER: {
88
+ (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>): QueryEngine;
89
+
90
+ ASC: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
91
+ DESC: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
92
+ ADD: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
93
+ REPLACE: (...args: Array<LiteralBase | Field | string | Array<LiteralBase | Field | string>>) => QueryEngine;
94
+
95
+ name: QueryEngine;
96
+ };
83
97
 
84
98
  declare public NOT: {
85
99
  (): QueryEngine;