@loomcore/api 0.1.95 → 0.1.98
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 -201
- package/README.md +77 -77
- package/dist/__tests__/common-test.utils.js +3 -5
- package/dist/__tests__/postgres-test-migrations/postgres-test-schema.js +266 -266
- package/dist/__tests__/postgres.test-database.js +8 -8
- package/dist/databases/migrations/migration-runner.js +21 -21
- package/dist/databases/mongo-db/utils/convert-operations-to-pipeline.util.js +65 -473
- package/dist/databases/operations/index.d.ts +3 -4
- package/dist/databases/operations/index.js +3 -4
- package/dist/databases/operations/{join.operation.d.ts → inner-join.operation.d.ts} +1 -1
- package/dist/databases/operations/{join.operation.js → inner-join.operation.js} +2 -2
- package/dist/databases/operations/left-join-many.operation.d.ts +7 -0
- package/dist/databases/operations/left-join-many.operation.js +15 -0
- package/dist/databases/operations/{join-many.operation.d.ts → left-join.operation.d.ts} +1 -1
- package/dist/databases/operations/{join-many.operation.js → left-join.operation.js} +2 -2
- package/dist/databases/operations/operation.d.ts +4 -5
- package/dist/databases/postgres/commands/postgres-batch-update.command.js +11 -12
- package/dist/databases/postgres/commands/postgres-create-many.command.js +4 -4
- package/dist/databases/postgres/commands/postgres-create.command.js +4 -4
- package/dist/databases/postgres/commands/postgres-full-update-by-id.command.js +14 -14
- package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.js +8 -8
- package/dist/databases/postgres/commands/postgres-update.command.js +8 -8
- package/dist/databases/postgres/migrations/__tests__/test-migration-helper.js +1 -0
- package/dist/databases/postgres/migrations/postgres-initial-schema.js +224 -224
- package/dist/databases/postgres/postgres.database.js +17 -17
- package/dist/databases/postgres/queries/postgres-get-all.query.js +4 -5
- package/dist/databases/postgres/queries/postgres-get-by-id.query.js +4 -5
- package/dist/databases/postgres/queries/postgres-get.query.js +4 -5
- package/dist/databases/postgres/utils/build-join-clauses.d.ts +1 -1
- package/dist/databases/postgres/utils/build-join-clauses.js +20 -363
- package/dist/databases/postgres/utils/build-select-clause.js +15 -27
- package/dist/databases/postgres/utils/does-table-exist.util.js +4 -4
- package/dist/databases/postgres/utils/transform-join-results.js +19 -120
- package/dist/models/initial-database-config.interface.d.ts +1 -0
- package/package.json +92 -92
- package/dist/databases/operations/join-through-many.operation.d.ts +0 -10
- package/dist/databases/operations/join-through-many.operation.js +0 -21
- package/dist/databases/operations/join-through.operation.d.ts +0 -10
- package/dist/databases/operations/join-through.operation.js +0 -21
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { JoinThroughMany } from '../../operations/join-through-many.operation.js';
|
|
1
|
+
import { LeftJoin } from '../../operations/left-join.operation.js';
|
|
2
|
+
import { InnerJoin } from '../../operations/inner-join.operation.js';
|
|
3
|
+
import { LeftJoinMany } from '../../operations/left-join-many.operation.js';
|
|
5
4
|
function resolveLocalFieldPath(localField, processedOperations) {
|
|
6
5
|
if (!localField.includes('.')) {
|
|
7
6
|
return localField;
|
|
8
7
|
}
|
|
9
8
|
const [parentAlias] = localField.split('.');
|
|
10
|
-
const parentJoin = processedOperations.find(op => (op instanceof
|
|
9
|
+
const parentJoin = processedOperations.find(op => (op instanceof LeftJoin || op instanceof InnerJoin || op instanceof LeftJoinMany) &&
|
|
11
10
|
op.as === parentAlias);
|
|
12
11
|
if (parentJoin) {
|
|
13
12
|
return `_joinData.${localField}`;
|
|
@@ -18,10 +17,10 @@ export function convertOperationsToPipeline(operations) {
|
|
|
18
17
|
let pipeline = [];
|
|
19
18
|
const processedOperations = [];
|
|
20
19
|
const joinAliases = operations
|
|
21
|
-
.filter(op => op instanceof
|
|
20
|
+
.filter(op => op instanceof LeftJoin || op instanceof InnerJoin || op instanceof LeftJoinMany)
|
|
22
21
|
.map(op => op.as);
|
|
23
22
|
operations.forEach(operation => {
|
|
24
|
-
if (operation instanceof
|
|
23
|
+
if (operation instanceof LeftJoin || operation instanceof InnerJoin) {
|
|
25
24
|
const needsObjectIdConversion = operation.foreignField === '_id';
|
|
26
25
|
const isNestedField = operation.localField.includes('.');
|
|
27
26
|
const resolvedLocalField = resolveLocalFieldPath(operation.localField, processedOperations);
|
|
@@ -99,7 +98,7 @@ export function convertOperationsToPipeline(operations) {
|
|
|
99
98
|
}
|
|
100
99
|
if (isNestedField) {
|
|
101
100
|
const [parentAlias] = operation.localField.split('.');
|
|
102
|
-
const parentJoin = processedOperations.find(op => (op instanceof
|
|
101
|
+
const parentJoin = processedOperations.find(op => (op instanceof LeftJoin || op instanceof InnerJoin || op instanceof LeftJoinMany) && op.as === parentAlias);
|
|
103
102
|
if (parentJoin) {
|
|
104
103
|
pipeline.push({
|
|
105
104
|
$addFields: {
|
|
@@ -141,7 +140,7 @@ export function convertOperationsToPipeline(operations) {
|
|
|
141
140
|
}
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
|
-
else if (operation instanceof
|
|
143
|
+
else if (operation instanceof LeftJoinMany) {
|
|
145
144
|
const needsObjectIdConversion = operation.foreignField === '_id';
|
|
146
145
|
const isNestedField = operation.localField.includes('.');
|
|
147
146
|
const resolvedLocalField = resolveLocalFieldPath(operation.localField, processedOperations);
|
|
@@ -185,171 +184,72 @@ export function convertOperationsToPipeline(operations) {
|
|
|
185
184
|
});
|
|
186
185
|
if (isNestedField) {
|
|
187
186
|
const [parentAlias] = operation.localField.split('.');
|
|
188
|
-
const parentJoin = processedOperations.find(op => (op instanceof
|
|
187
|
+
const parentJoin = processedOperations.find(op => (op instanceof LeftJoin || op instanceof InnerJoin || op instanceof LeftJoinMany) && op.as === parentAlias);
|
|
189
188
|
if (parentJoin) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
]
|
|
201
|
-
|
|
189
|
+
if (parentJoin instanceof LeftJoinMany) {
|
|
190
|
+
const grandparentJoin = processedOperations
|
|
191
|
+
.slice(0, processedOperations.indexOf(parentJoin))
|
|
192
|
+
.reverse()
|
|
193
|
+
.find(op => op instanceof LeftJoin || op instanceof InnerJoin);
|
|
194
|
+
if (grandparentJoin) {
|
|
195
|
+
pipeline.push({
|
|
196
|
+
$addFields: {
|
|
197
|
+
_joinData: {
|
|
198
|
+
$mergeObjects: [
|
|
199
|
+
{ $ifNull: ['$_joinData', {}] },
|
|
200
|
+
{
|
|
201
|
+
[grandparentJoin.as]: {
|
|
202
|
+
$mergeObjects: [
|
|
203
|
+
{ $ifNull: [`$_joinData.${grandparentJoin.as}`, {}] },
|
|
204
|
+
{
|
|
205
|
+
[operation.as]: {
|
|
206
|
+
$ifNull: [`$_joinData.${operation.as}`, []]
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
]
|
|
202
213
|
}
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
pipeline.push({
|
|
208
|
-
$unset: `_joinData.${operation.as}`
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
pipeline.push({
|
|
215
|
-
$lookup: {
|
|
216
|
-
from: operation.from,
|
|
217
|
-
localField: resolvedLocalField,
|
|
218
|
-
foreignField: operation.foreignField,
|
|
219
|
-
as: `${operation.as}_temp`
|
|
220
|
-
}
|
|
221
|
-
}, {
|
|
222
|
-
$addFields: {
|
|
223
|
-
_joinData: {
|
|
224
|
-
$mergeObjects: [
|
|
225
|
-
{ $ifNull: ['$_joinData', {}] },
|
|
226
|
-
{ [operation.as]: `$${operation.as}_temp` }
|
|
227
|
-
]
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}, {
|
|
231
|
-
$project: {
|
|
232
|
-
[`${operation.as}_temp`]: 0
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
else if (operation instanceof JoinThrough) {
|
|
238
|
-
const needsObjectIdConversion = operation.foreignField === '_id';
|
|
239
|
-
const isNestedField = operation.localField.includes('.');
|
|
240
|
-
const resolvedLocalField = resolveLocalFieldPath(operation.localField, processedOperations);
|
|
241
|
-
if (needsObjectIdConversion || isNestedField) {
|
|
242
|
-
pipeline.push({
|
|
243
|
-
$lookup: {
|
|
244
|
-
from: operation.through,
|
|
245
|
-
let: {
|
|
246
|
-
localId: {
|
|
247
|
-
$cond: [
|
|
248
|
-
{ $eq: [{ $type: `$${resolvedLocalField}` }, 'string'] },
|
|
249
|
-
{ $toObjectId: `$${resolvedLocalField}` },
|
|
250
|
-
`$${resolvedLocalField}`
|
|
251
|
-
]
|
|
214
|
+
}
|
|
215
|
+
});
|
|
252
216
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
'$$localId'
|
|
267
|
-
]
|
|
217
|
+
else {
|
|
218
|
+
pipeline.push({
|
|
219
|
+
$addFields: {
|
|
220
|
+
_joinData: {
|
|
221
|
+
$mergeObjects: [
|
|
222
|
+
{ $ifNull: ['$_joinData', {}] },
|
|
223
|
+
{
|
|
224
|
+
[operation.as]: {
|
|
225
|
+
$ifNull: [`$_joinData.${operation.as}`, []]
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
}
|
|
268
230
|
}
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
{ $limit: 1 }
|
|
272
|
-
],
|
|
273
|
-
as: `${operation.as}_through`
|
|
274
|
-
}
|
|
275
|
-
}, {
|
|
276
|
-
$unwind: {
|
|
277
|
-
path: `$${operation.as}_through`,
|
|
278
|
-
preserveNullAndEmptyArrays: true
|
|
279
|
-
}
|
|
280
|
-
}, {
|
|
281
|
-
$lookup: {
|
|
282
|
-
from: operation.from,
|
|
283
|
-
let: {
|
|
284
|
-
foreignId: {
|
|
285
|
-
$cond: [
|
|
286
|
-
{ $eq: [{ $type: `$${operation.as}_through.${operation.throughForeignField}` }, 'string'] },
|
|
287
|
-
{ $toObjectId: `$${operation.as}_through.${operation.throughForeignField}` },
|
|
288
|
-
`$${operation.as}_through.${operation.throughForeignField}`
|
|
289
|
-
]
|
|
231
|
+
});
|
|
290
232
|
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
{
|
|
294
|
-
$
|
|
295
|
-
|
|
296
|
-
$
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
pipeline.push({
|
|
236
|
+
$addFields: {
|
|
237
|
+
_joinData: {
|
|
238
|
+
$mergeObjects: [
|
|
239
|
+
{ $ifNull: ['$_joinData', {}] },
|
|
297
240
|
{
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
241
|
+
[parentAlias]: {
|
|
242
|
+
$mergeObjects: [
|
|
243
|
+
{ $ifNull: [`$_joinData.${parentAlias}`, {}] },
|
|
244
|
+
{ [operation.as]: { $ifNull: [`$_joinData.${operation.as}`, []] } }
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
}
|
|
305
248
|
]
|
|
306
249
|
}
|
|
307
250
|
}
|
|
308
|
-
}
|
|
309
|
-
],
|
|
310
|
-
as: `${operation.as}_temp`
|
|
311
|
-
}
|
|
312
|
-
}, {
|
|
313
|
-
$unwind: {
|
|
314
|
-
path: `$${operation.as}_temp`,
|
|
315
|
-
preserveNullAndEmptyArrays: true
|
|
316
|
-
}
|
|
317
|
-
}, {
|
|
318
|
-
$addFields: {
|
|
319
|
-
_joinData: {
|
|
320
|
-
$mergeObjects: [
|
|
321
|
-
{ $ifNull: ['$_joinData', {}] },
|
|
322
|
-
{ [operation.as]: `$${operation.as}_temp` }
|
|
323
|
-
]
|
|
251
|
+
});
|
|
324
252
|
}
|
|
325
|
-
}
|
|
326
|
-
}, {
|
|
327
|
-
$project: {
|
|
328
|
-
[`${operation.as}_through`]: 0,
|
|
329
|
-
[`${operation.as}_temp`]: 0
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
if (isNestedField) {
|
|
333
|
-
const [parentAlias] = operation.localField.split('.');
|
|
334
|
-
const parentJoin = processedOperations.find(op => (op instanceof Join || op instanceof JoinThrough) && op.as === parentAlias);
|
|
335
|
-
if (parentJoin) {
|
|
336
|
-
pipeline.push({
|
|
337
|
-
$addFields: {
|
|
338
|
-
_joinData: {
|
|
339
|
-
$mergeObjects: [
|
|
340
|
-
{ $ifNull: ['$_joinData', {}] },
|
|
341
|
-
{
|
|
342
|
-
[parentAlias]: {
|
|
343
|
-
$mergeObjects: [
|
|
344
|
-
{ $ifNull: [`$_joinData.${parentAlias}`, {}] },
|
|
345
|
-
{ [operation.as]: `$_joinData.${operation.as}` }
|
|
346
|
-
]
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
]
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
253
|
pipeline.push({
|
|
354
254
|
$unset: `_joinData.${operation.as}`
|
|
355
255
|
});
|
|
@@ -357,59 +257,13 @@ export function convertOperationsToPipeline(operations) {
|
|
|
357
257
|
}
|
|
358
258
|
}
|
|
359
259
|
else {
|
|
360
|
-
const isNestedFieldElse = operation.localField.includes('.');
|
|
361
|
-
const resolvedLocalFieldElse = resolveLocalFieldPath(operation.localField, processedOperations);
|
|
362
|
-
if (isNestedFieldElse) {
|
|
363
|
-
pipeline.push({
|
|
364
|
-
$lookup: {
|
|
365
|
-
from: operation.through,
|
|
366
|
-
let: { localId: `$${resolvedLocalFieldElse}` },
|
|
367
|
-
pipeline: [
|
|
368
|
-
{
|
|
369
|
-
$match: {
|
|
370
|
-
$expr: {
|
|
371
|
-
$eq: [`$${operation.throughLocalField}`, '$$localId']
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
},
|
|
375
|
-
{ $limit: 1 }
|
|
376
|
-
],
|
|
377
|
-
as: `${operation.as}_through`
|
|
378
|
-
}
|
|
379
|
-
}, {
|
|
380
|
-
$unwind: {
|
|
381
|
-
path: `$${operation.as}_through`,
|
|
382
|
-
preserveNullAndEmptyArrays: true
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
pipeline.push({
|
|
388
|
-
$lookup: {
|
|
389
|
-
from: operation.through,
|
|
390
|
-
localField: resolvedLocalFieldElse,
|
|
391
|
-
foreignField: operation.throughLocalField,
|
|
392
|
-
as: `${operation.as}_through`
|
|
393
|
-
}
|
|
394
|
-
}, {
|
|
395
|
-
$unwind: {
|
|
396
|
-
path: `$${operation.as}_through`,
|
|
397
|
-
preserveNullAndEmptyArrays: true
|
|
398
|
-
}
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
260
|
pipeline.push({
|
|
402
261
|
$lookup: {
|
|
403
262
|
from: operation.from,
|
|
404
|
-
localField:
|
|
263
|
+
localField: resolvedLocalField,
|
|
405
264
|
foreignField: operation.foreignField,
|
|
406
265
|
as: `${operation.as}_temp`
|
|
407
266
|
}
|
|
408
|
-
}, {
|
|
409
|
-
$unwind: {
|
|
410
|
-
path: `$${operation.as}_temp`,
|
|
411
|
-
preserveNullAndEmptyArrays: true
|
|
412
|
-
}
|
|
413
267
|
}, {
|
|
414
268
|
$addFields: {
|
|
415
269
|
_joinData: {
|
|
@@ -421,271 +275,9 @@ export function convertOperationsToPipeline(operations) {
|
|
|
421
275
|
}
|
|
422
276
|
}, {
|
|
423
277
|
$project: {
|
|
424
|
-
[`${operation.as}_through`]: 0,
|
|
425
278
|
[`${operation.as}_temp`]: 0
|
|
426
279
|
}
|
|
427
280
|
});
|
|
428
|
-
if (isNestedFieldElse) {
|
|
429
|
-
const [parentAlias] = operation.localField.split('.');
|
|
430
|
-
const parentJoin = processedOperations.find(op => (op instanceof Join || op instanceof JoinThrough) && op.as === parentAlias);
|
|
431
|
-
if (parentJoin) {
|
|
432
|
-
pipeline.push({
|
|
433
|
-
$addFields: {
|
|
434
|
-
_joinData: {
|
|
435
|
-
$mergeObjects: [
|
|
436
|
-
{ $ifNull: ['$_joinData', {}] },
|
|
437
|
-
{
|
|
438
|
-
[parentAlias]: {
|
|
439
|
-
$mergeObjects: [
|
|
440
|
-
{ $ifNull: [`$_joinData.${parentAlias}`, {}] },
|
|
441
|
-
{ [operation.as]: `$_joinData.${operation.as}` }
|
|
442
|
-
]
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
]
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
pipeline.push({
|
|
450
|
-
$unset: `_joinData.${operation.as}`
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
else if (operation instanceof JoinThroughMany) {
|
|
457
|
-
const needsObjectIdConversion = operation.foreignField === '_id';
|
|
458
|
-
const isNestedField = operation.localField.includes('.');
|
|
459
|
-
const resolvedLocalField = resolveLocalFieldPath(operation.localField, processedOperations);
|
|
460
|
-
if (needsObjectIdConversion || isNestedField) {
|
|
461
|
-
pipeline.push({
|
|
462
|
-
$lookup: {
|
|
463
|
-
from: operation.through,
|
|
464
|
-
let: {
|
|
465
|
-
localId: {
|
|
466
|
-
$cond: [
|
|
467
|
-
{ $eq: [{ $type: `$${resolvedLocalField}` }, 'string'] },
|
|
468
|
-
{ $toObjectId: `$${resolvedLocalField}` },
|
|
469
|
-
`$${resolvedLocalField}`
|
|
470
|
-
]
|
|
471
|
-
}
|
|
472
|
-
},
|
|
473
|
-
pipeline: [
|
|
474
|
-
{
|
|
475
|
-
$match: {
|
|
476
|
-
$expr: {
|
|
477
|
-
$eq: [
|
|
478
|
-
{
|
|
479
|
-
$cond: [
|
|
480
|
-
{ $eq: [{ $type: `$${operation.throughLocalField}` }, 'string'] },
|
|
481
|
-
{ $toObjectId: `$${operation.throughLocalField}` },
|
|
482
|
-
`$${operation.throughLocalField}`
|
|
483
|
-
]
|
|
484
|
-
},
|
|
485
|
-
'$$localId'
|
|
486
|
-
]
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
],
|
|
491
|
-
as: `${operation.as}_through`
|
|
492
|
-
}
|
|
493
|
-
}, {
|
|
494
|
-
$unwind: {
|
|
495
|
-
path: `$${operation.as}_through`,
|
|
496
|
-
preserveNullAndEmptyArrays: true
|
|
497
|
-
}
|
|
498
|
-
}, {
|
|
499
|
-
$lookup: {
|
|
500
|
-
from: operation.from,
|
|
501
|
-
let: {
|
|
502
|
-
foreignId: {
|
|
503
|
-
$cond: [
|
|
504
|
-
{ $eq: [{ $type: `$${operation.as}_through.${operation.throughForeignField}` }, 'string'] },
|
|
505
|
-
{ $toObjectId: `$${operation.as}_through.${operation.throughForeignField}` },
|
|
506
|
-
`$${operation.as}_through.${operation.throughForeignField}`
|
|
507
|
-
]
|
|
508
|
-
}
|
|
509
|
-
},
|
|
510
|
-
pipeline: [
|
|
511
|
-
{
|
|
512
|
-
$match: {
|
|
513
|
-
$expr: {
|
|
514
|
-
$eq: [
|
|
515
|
-
{
|
|
516
|
-
$cond: [
|
|
517
|
-
{ $eq: [{ $type: `$${operation.foreignField}` }, 'string'] },
|
|
518
|
-
{ $toObjectId: `$${operation.foreignField}` },
|
|
519
|
-
`$${operation.foreignField}`
|
|
520
|
-
]
|
|
521
|
-
},
|
|
522
|
-
'$$foreignId'
|
|
523
|
-
]
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
],
|
|
528
|
-
as: `${operation.as}_temp`
|
|
529
|
-
}
|
|
530
|
-
}, {
|
|
531
|
-
$group: {
|
|
532
|
-
_id: '$_id',
|
|
533
|
-
root: { $first: '$$ROOT' },
|
|
534
|
-
[`${operation.as}_temp_grouped`]: { $push: { $arrayElemAt: [`$${operation.as}_temp`, 0] } }
|
|
535
|
-
}
|
|
536
|
-
}, {
|
|
537
|
-
$replaceRoot: {
|
|
538
|
-
newRoot: {
|
|
539
|
-
$mergeObjects: [
|
|
540
|
-
'$root',
|
|
541
|
-
{
|
|
542
|
-
_joinData: {
|
|
543
|
-
$mergeObjects: [
|
|
544
|
-
{ $ifNull: ['$root._joinData', {}] },
|
|
545
|
-
{ [operation.as]: `$${operation.as}_temp_grouped` }
|
|
546
|
-
]
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
]
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}, {
|
|
553
|
-
$project: {
|
|
554
|
-
[`${operation.as}_through`]: 0,
|
|
555
|
-
[`${operation.as}_temp`]: 0,
|
|
556
|
-
[`${operation.as}_temp_grouped`]: 0
|
|
557
|
-
}
|
|
558
|
-
});
|
|
559
|
-
if (isNestedField) {
|
|
560
|
-
const [parentAlias] = operation.localField.split('.');
|
|
561
|
-
const parentJoin = processedOperations.find(op => (op instanceof Join || op instanceof JoinThrough) && op.as === parentAlias);
|
|
562
|
-
if (parentJoin) {
|
|
563
|
-
pipeline.push({
|
|
564
|
-
$addFields: {
|
|
565
|
-
_joinData: {
|
|
566
|
-
$mergeObjects: [
|
|
567
|
-
{ $ifNull: ['$_joinData', {}] },
|
|
568
|
-
{
|
|
569
|
-
[parentAlias]: {
|
|
570
|
-
$mergeObjects: [
|
|
571
|
-
{ $ifNull: [`$_joinData.${parentAlias}`, {}] },
|
|
572
|
-
{ [operation.as]: `$_joinData.${operation.as}` }
|
|
573
|
-
]
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
]
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
});
|
|
580
|
-
pipeline.push({
|
|
581
|
-
$unset: `_joinData.${operation.as}`
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
else {
|
|
587
|
-
const isNestedFieldElse = operation.localField.includes('.');
|
|
588
|
-
const resolvedLocalFieldElse = resolveLocalFieldPath(operation.localField, processedOperations);
|
|
589
|
-
if (isNestedFieldElse) {
|
|
590
|
-
pipeline.push({
|
|
591
|
-
$lookup: {
|
|
592
|
-
from: operation.through,
|
|
593
|
-
let: { localId: `$${resolvedLocalFieldElse}` },
|
|
594
|
-
pipeline: [
|
|
595
|
-
{
|
|
596
|
-
$match: {
|
|
597
|
-
$expr: {
|
|
598
|
-
$eq: [`$${operation.throughLocalField}`, '$$localId']
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
],
|
|
603
|
-
as: `${operation.as}_through`
|
|
604
|
-
}
|
|
605
|
-
}, {
|
|
606
|
-
$unwind: {
|
|
607
|
-
path: `$${operation.as}_through`,
|
|
608
|
-
preserveNullAndEmptyArrays: true
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
613
|
-
pipeline.push({
|
|
614
|
-
$lookup: {
|
|
615
|
-
from: operation.through,
|
|
616
|
-
localField: resolvedLocalFieldElse,
|
|
617
|
-
foreignField: operation.throughLocalField,
|
|
618
|
-
as: `${operation.as}_through`
|
|
619
|
-
}
|
|
620
|
-
}, {
|
|
621
|
-
$unwind: {
|
|
622
|
-
path: `$${operation.as}_through`,
|
|
623
|
-
preserveNullAndEmptyArrays: true
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
pipeline.push({
|
|
628
|
-
$lookup: {
|
|
629
|
-
from: operation.from,
|
|
630
|
-
localField: `${operation.as}_through.${operation.throughForeignField}`,
|
|
631
|
-
foreignField: operation.foreignField,
|
|
632
|
-
as: `${operation.as}_temp`
|
|
633
|
-
}
|
|
634
|
-
}, {
|
|
635
|
-
$group: {
|
|
636
|
-
_id: '$_id',
|
|
637
|
-
root: { $first: '$$ROOT' },
|
|
638
|
-
[`${operation.as}_temp_grouped`]: { $push: { $arrayElemAt: [`$${operation.as}_temp`, 0] } }
|
|
639
|
-
}
|
|
640
|
-
}, {
|
|
641
|
-
$replaceRoot: {
|
|
642
|
-
newRoot: {
|
|
643
|
-
$mergeObjects: [
|
|
644
|
-
'$root',
|
|
645
|
-
{
|
|
646
|
-
_joinData: {
|
|
647
|
-
$mergeObjects: [
|
|
648
|
-
{ $ifNull: ['$root._joinData', {}] },
|
|
649
|
-
{ [operation.as]: `$${operation.as}_temp_grouped` }
|
|
650
|
-
]
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
]
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}, {
|
|
657
|
-
$project: {
|
|
658
|
-
[`${operation.as}_through`]: 0,
|
|
659
|
-
[`${operation.as}_temp`]: 0,
|
|
660
|
-
[`${operation.as}_temp_grouped`]: 0
|
|
661
|
-
}
|
|
662
|
-
});
|
|
663
|
-
if (isNestedFieldElse) {
|
|
664
|
-
const [parentAlias] = operation.localField.split('.');
|
|
665
|
-
const parentJoin = processedOperations.find(op => (op instanceof Join || op instanceof JoinThrough) && op.as === parentAlias);
|
|
666
|
-
if (parentJoin) {
|
|
667
|
-
pipeline.push({
|
|
668
|
-
$addFields: {
|
|
669
|
-
_joinData: {
|
|
670
|
-
$mergeObjects: [
|
|
671
|
-
{ $ifNull: ['$_joinData', {}] },
|
|
672
|
-
{
|
|
673
|
-
[parentAlias]: {
|
|
674
|
-
$mergeObjects: [
|
|
675
|
-
{ $ifNull: [`$_joinData.${parentAlias}`, {}] },
|
|
676
|
-
{ [operation.as]: `$_joinData.${operation.as}` }
|
|
677
|
-
]
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
]
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
});
|
|
684
|
-
pipeline.push({
|
|
685
|
-
$unset: `_joinData.${operation.as}`
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
281
|
}
|
|
690
282
|
}
|
|
691
283
|
processedOperations.push(operation);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export * from './operation.js';
|
|
2
|
-
export * from './join.operation.js';
|
|
3
|
-
export * from './join
|
|
4
|
-
export * from './join-
|
|
5
|
-
export * from './join-through-many.operation.js';
|
|
2
|
+
export * from './left-join.operation.js';
|
|
3
|
+
export * from './inner-join.operation.js';
|
|
4
|
+
export * from './left-join-many.operation.js';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export * from './operation.js';
|
|
2
|
-
export * from './join.operation.js';
|
|
3
|
-
export * from './join
|
|
4
|
-
export * from './join-
|
|
5
|
-
export * from './join-through-many.operation.js';
|
|
2
|
+
export * from './left-join.operation.js';
|
|
3
|
+
export * from './inner-join.operation.js';
|
|
4
|
+
export * from './left-join-many.operation.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export class
|
|
1
|
+
export class InnerJoin {
|
|
2
2
|
from;
|
|
3
3
|
localField;
|
|
4
4
|
foreignField;
|
|
5
5
|
as;
|
|
6
6
|
constructor(from, localField, foreignField, as) {
|
|
7
7
|
if (from === as) {
|
|
8
|
-
throw new Error(`
|
|
8
|
+
throw new Error(`InnerJoin alias "${as}" must be different from table name "${from}". The alias is used to identify the join result and must be unique.`);
|
|
9
9
|
}
|
|
10
10
|
this.from = from;
|
|
11
11
|
this.localField = localField;
|