@omegup/msync 0.1.45 → 0.1.46
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/index.d.ts +35 -11
- package/index.esm.js +315 -177
- package/index.js +316 -176
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -219,7 +219,7 @@ const { root, ctx } = Field;
|
|
|
219
219
|
const asAccumulator = (x) => x;
|
|
220
220
|
const $sum_ = (expr) => ({ raw: f => asAccumulator({ $sum: expr.raw(f).get() }) });
|
|
221
221
|
const $sum = (expr) => ({
|
|
222
|
-
group: $sum_(ite(root().of('old').expr(), subtract(val(0), $ifNull(sub(expr, root().of('v')), val(0))), sub(expr, root().of('v')))),
|
|
222
|
+
group: $sum_(ite(root().of('deleted').expr(), val(0), ite(root().of('old').expr(), subtract(val(0), $ifNull(sub(expr, root().of('v')), val(0))), sub(expr, root().of('v'))))),
|
|
223
223
|
merge: (x, y) => add($ifNull(x, val(0)), y),
|
|
224
224
|
});
|
|
225
225
|
const $accumulator_ = (init, accumulateArgs, accumulate, merge) => {
|
|
@@ -242,7 +242,13 @@ const $accumulator = (init, accumulateArgs, accumulate, merge) => ({
|
|
|
242
242
|
});
|
|
243
243
|
const $countDict = (expr) => $accumulator(function () {
|
|
244
244
|
return {};
|
|
245
|
-
}, [
|
|
245
|
+
}, [
|
|
246
|
+
sub(expr, root().of('v')),
|
|
247
|
+
root().of('old').expr(),
|
|
248
|
+
root().of('deleted').expr(),
|
|
249
|
+
], function (a, k, old, deleted) {
|
|
250
|
+
if (deleted)
|
|
251
|
+
return a;
|
|
246
252
|
let y = (a[k] || 0) + (old ? -1 : 1);
|
|
247
253
|
return y ? (a[k] = y) : delete a[k], a;
|
|
248
254
|
}, function (a, b) {
|
|
@@ -253,7 +259,13 @@ const $countDict = (expr) => $accumulator(function () {
|
|
|
253
259
|
});
|
|
254
260
|
const $countDictArray = (expr) => $accumulator(function () {
|
|
255
261
|
return {};
|
|
256
|
-
}, [
|
|
262
|
+
}, [
|
|
263
|
+
sub(expr, root().of('v')),
|
|
264
|
+
root().of('old').expr(),
|
|
265
|
+
root().of('deleted').expr(),
|
|
266
|
+
], function (a, keys, old, deleted) {
|
|
267
|
+
if (deleted)
|
|
268
|
+
return a;
|
|
257
269
|
keys.forEach(k => {
|
|
258
270
|
const y = (a[k] || 0) + (old ? -1 : 1);
|
|
259
271
|
if (y)
|
|
@@ -274,7 +286,10 @@ const $pushDict = (key, value) => $accumulator(function () {
|
|
|
274
286
|
sub(key, root().of('v')),
|
|
275
287
|
sub(value, root().of('v')),
|
|
276
288
|
root().of('old').expr(),
|
|
277
|
-
|
|
289
|
+
root().of('deleted').expr(),
|
|
290
|
+
], function (ra, k, v, old, deleted) {
|
|
291
|
+
if (deleted)
|
|
292
|
+
return ra;
|
|
278
293
|
let a = { ...ra };
|
|
279
294
|
const equal = (a, b) => {
|
|
280
295
|
if (!a || !b)
|
|
@@ -402,6 +417,7 @@ const assertEqual = () => ({
|
|
|
402
417
|
forward1: id,
|
|
403
418
|
backward1: id,
|
|
404
419
|
});
|
|
420
|
+
const literalsEqaul = (_) => assertEqual();
|
|
405
421
|
const omitRORec = () => assertEqual();
|
|
406
422
|
const omitPick = () => assertEqual();
|
|
407
423
|
const translateOmit = () => assertEqual();
|
|
@@ -420,7 +436,7 @@ const filter = ({ as, cond, expr, limit, }) => asExpr({
|
|
|
420
436
|
input: expr.raw(f).get(),
|
|
421
437
|
as,
|
|
422
438
|
cond: cond.raw(f).get(),
|
|
423
|
-
limit: limit
|
|
439
|
+
...(limit ? { limit: limit.raw(f).get() } : {}),
|
|
424
440
|
},
|
|
425
441
|
}),
|
|
426
442
|
});
|
|
@@ -564,9 +580,23 @@ const subGroup = (id, args, addGrp) => {
|
|
|
564
580
|
const part = filterDefined(array(ite(eqTyped(root().of('after').expr(), nil), nil, field({
|
|
565
581
|
v: ['v', root().of('after').expr()],
|
|
566
582
|
old: ['old', val(false)],
|
|
583
|
+
deleted: [
|
|
584
|
+
'deleted',
|
|
585
|
+
root()
|
|
586
|
+
.of('deleted')
|
|
587
|
+
.of('after')
|
|
588
|
+
.expr(),
|
|
589
|
+
],
|
|
567
590
|
})), ite(eqTyped(root().of('before').expr(), nil), nil, field({
|
|
568
591
|
v: ['v', root().of('before').expr()],
|
|
569
592
|
old: ['old', val(true)],
|
|
593
|
+
deleted: [
|
|
594
|
+
'deleted',
|
|
595
|
+
root()
|
|
596
|
+
.of('deleted')
|
|
597
|
+
.of('before')
|
|
598
|
+
.expr(),
|
|
599
|
+
],
|
|
570
600
|
}))));
|
|
571
601
|
const replaceWith = (expr) => $replaceWith_(expr);
|
|
572
602
|
return link()
|
|
@@ -1052,9 +1082,10 @@ const $setDelta = (updater) => {
|
|
|
1052
1082
|
after1: ['after1', 'after'],
|
|
1053
1083
|
before1: ['before1', 'before'],
|
|
1054
1084
|
};
|
|
1055
|
-
const
|
|
1085
|
+
const side = (k) => root().of(k);
|
|
1086
|
+
const update = (k) => subUpdater(weaken(updater), side(k));
|
|
1056
1087
|
return link()
|
|
1057
|
-
.with($setEach(k => to(
|
|
1088
|
+
.with($setEach(k => to(side(k).expr()), dict))
|
|
1058
1089
|
.with($setEach(update, dict))
|
|
1059
1090
|
.with($replaceWithEach(field => root().of(`${field}1`).expr()))
|
|
1060
1091
|
.with($setEach(k => to(nil), dict)).stages;
|
|
@@ -1088,147 +1119,229 @@ const dualIn = operator();
|
|
|
1088
1119
|
const $in = dualIn('$in');
|
|
1089
1120
|
const $nin = dualIn('$nin');
|
|
1090
1121
|
|
|
1091
|
-
const $
|
|
1092
|
-
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1122
|
+
const $matchDelta = (query) => concatStages($replaceWithDelta(ite(query, root().expr(), nil)), matchDelta());
|
|
1123
|
+
const matchDelta = () => {
|
|
1124
|
+
const part = (side) => root().of(side).expr();
|
|
1125
|
+
return $match_($expr(ne(part('before'))(part('after'))));
|
|
1126
|
+
};
|
|
1127
|
+
|
|
1128
|
+
const $match = (query) => ({
|
|
1129
|
+
raw: $match1($expr(query)),
|
|
1130
|
+
delta: $matchDelta(query),
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
const joinIdOf = (k, k1, k1Id, k2Id) => {
|
|
1134
|
+
if (k === k1)
|
|
1135
|
+
return k1Id;
|
|
1136
|
+
if (typeof k === 'string')
|
|
1137
|
+
return k2Id;
|
|
1138
|
+
const idOf = (key) => (key === k1 ? k1Id : k2Id);
|
|
1139
|
+
return concat(idOf(k[0]), val(k[1]), idOf(k[2]));
|
|
1140
|
+
};
|
|
1141
|
+
const andAlso = (probe, keep) => ite(eqTyped(probe, nil), nil, keep);
|
|
1142
|
+
const notObjAndAlso = (probe, keep) => ite(eqTyped(probe, field({})), nil, keep);
|
|
1143
|
+
const $unwindDelta = (k1, k2, k, includeNull1, includeNull2) => {
|
|
1144
|
+
const emptyArr = array();
|
|
1145
|
+
const src = root();
|
|
1146
|
+
const k2Arr = (side) => src.of(side).of(k2).expr();
|
|
1147
|
+
const k2OrEmpty = (side) => $ifNull(k2Arr(side), emptyArr);
|
|
1148
|
+
const k2Empty = (side) => eq(k2Arr(side))(emptyArr);
|
|
1149
|
+
const beforeItems = k2OrEmpty('before');
|
|
1150
|
+
const afterItems = k2OrEmpty('after');
|
|
1151
|
+
const beforeIds = $map1(beforeItems, (item) => item.of('_id').expr());
|
|
1152
|
+
const newByK2Id = filter({
|
|
1153
|
+
expr: afterItems,
|
|
1154
|
+
as: 'a',
|
|
1155
|
+
cond: not(inArray(ctx()('a').of('_id').expr(), beforeIds)),
|
|
1156
|
+
});
|
|
1157
|
+
const oldByK2Id = $map0({
|
|
1158
|
+
input: beforeItems,
|
|
1159
|
+
as: 'b',
|
|
1160
|
+
expr: field({
|
|
1161
|
+
before: ['before', ctx()('b').expr()],
|
|
1162
|
+
after: [
|
|
1163
|
+
'after',
|
|
1164
|
+
first$1(filter({
|
|
1165
|
+
expr: afterItems,
|
|
1166
|
+
as: 'a',
|
|
1167
|
+
cond: eq(ctx()('a').of('_id').expr())(ctx()('b').of('_id').expr()),
|
|
1168
|
+
})),
|
|
1169
|
+
],
|
|
1170
|
+
}),
|
|
1171
|
+
});
|
|
1172
|
+
const k1Slot = (fill) => array(field({
|
|
1173
|
+
before: [
|
|
1174
|
+
'before',
|
|
1175
|
+
$ifNull(first$1(beforeItems), fill),
|
|
1176
|
+
],
|
|
1177
|
+
after: [
|
|
1178
|
+
'after',
|
|
1179
|
+
$ifNull(first$1(afterItems), fill),
|
|
1180
|
+
],
|
|
1181
|
+
}));
|
|
1182
|
+
const kept = k === k1 ? k1Slot(nil) : oldByK2Id;
|
|
1183
|
+
const added = k === k1 ? emptyArr : newByK2Id;
|
|
1184
|
+
const k1Delta = field({
|
|
1185
|
+
before: [
|
|
1186
|
+
'before',
|
|
1187
|
+
$ifNull(src.of('before').of(k1).expr(), nil),
|
|
1188
|
+
],
|
|
1189
|
+
after: [
|
|
1190
|
+
'after',
|
|
1191
|
+
$ifNull(src.of('after').of(k1).expr(), nil),
|
|
1192
|
+
],
|
|
1193
|
+
});
|
|
1194
|
+
const unwindJoin = ({ kept, added, padToNull, isPad, join, }) => {
|
|
1195
|
+
const newDeltas = $map0({
|
|
1196
|
+
input: added,
|
|
1097
1197
|
as: 'a',
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
in: {
|
|
1119
|
-
before: '$$b',
|
|
1120
|
-
after: {
|
|
1121
|
-
$ifNull: [
|
|
1122
|
-
{
|
|
1123
|
-
$first: {
|
|
1124
|
-
$filter: {
|
|
1125
|
-
input: `$after.${k2}`,
|
|
1126
|
-
as: 'a',
|
|
1127
|
-
cond: { $eq: ['$$a._id', '$$b._id'] },
|
|
1128
|
-
},
|
|
1129
|
-
},
|
|
1130
|
-
},
|
|
1131
|
-
null,
|
|
1132
|
-
],
|
|
1133
|
-
},
|
|
1134
|
-
},
|
|
1135
|
-
},
|
|
1136
|
-
};
|
|
1137
|
-
const ifNull = (k, part, str = `$${k}.${part}._id`) => outer2 && k == k2 ? { $ifNull: [str, 'null'] } : str;
|
|
1138
|
-
const interDot = ([a, b]) => [a, middle ?? '.', b];
|
|
1139
|
-
const partReplace = (part) => {
|
|
1140
|
-
const def = {
|
|
1141
|
-
_id: k
|
|
1142
|
-
? ifNull(k, part)
|
|
1143
|
-
: {
|
|
1144
|
-
$concat: interDot([k1, k2].sort().map(k => ifNull(k, part))),
|
|
1145
|
-
},
|
|
1146
|
-
[k1]: `$${k1}.${part}`,
|
|
1147
|
-
[k2]: outer2
|
|
1148
|
-
? {
|
|
1149
|
-
$cond: {
|
|
1150
|
-
if: `$${k2}.${part}._id`,
|
|
1151
|
-
then: `$${k2}.${part}`,
|
|
1152
|
-
else: null,
|
|
1153
|
-
},
|
|
1154
|
-
}
|
|
1155
|
-
: `$${k2}.${part}`,
|
|
1198
|
+
expr: field({
|
|
1199
|
+
before: ['before', nil],
|
|
1200
|
+
after: ['after', ctx()('a').expr()],
|
|
1201
|
+
}),
|
|
1202
|
+
});
|
|
1203
|
+
const deltas = mergeObjects(field(map1(k1, k1Delta)), field(map1(k2, concatArray(kept, newDeltas))));
|
|
1204
|
+
const doc = root();
|
|
1205
|
+
const parentId = doc.of('_id').expr();
|
|
1206
|
+
const k1At = (side) => doc.of(k1).of(side).expr();
|
|
1207
|
+
const k2Raw = (side) => doc.of(k2).of(side).expr();
|
|
1208
|
+
const docK2Null = root();
|
|
1209
|
+
const k2Keep = (side) => docK2Null.of(k2).of(side).expr();
|
|
1210
|
+
const k2At = (side) => padToNull(k2Raw(side), k2Keep(side));
|
|
1211
|
+
const rowOf = (id, a, b) => mergeObjects(mergeObjects(field({ _id: ['_id', id] }), field(map1(k1, a))), field(map1(k2, b)));
|
|
1212
|
+
const docK1 = root();
|
|
1213
|
+
const k2RawK1 = (side) => docK1.of(k2).of(side).expr();
|
|
1214
|
+
const k2KeepK1K2 = (side) => root().of(k2).of(side).expr();
|
|
1215
|
+
const rowOnK1 = (side) => {
|
|
1216
|
+
const t = docK1.of(k1).of(side);
|
|
1217
|
+
return rowOf(t.of('_id').expr(), t.expr(), padToNull(k2RawK1(side), k2KeepK1K2(side)));
|
|
1156
1218
|
};
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
if: skipNulls.length === 1 ? skipNulls[0] : { $or: skipNulls },
|
|
1163
|
-
then: null,
|
|
1164
|
-
else: def,
|
|
1165
|
-
},
|
|
1219
|
+
const docK2 = root();
|
|
1220
|
+
const k1AtK2 = (side) => docK2.of(k1).of(side).expr();
|
|
1221
|
+
const rowOnK2 = (side) => {
|
|
1222
|
+
const u = docK2.of(k2).of(side);
|
|
1223
|
+
return rowOf(u.of('_id').expr(), k1AtK2(side), u.expr());
|
|
1166
1224
|
};
|
|
1225
|
+
const docK1K2 = root();
|
|
1226
|
+
const k1AtK1K2 = (side) => docK1K2.of(k1).of(side).expr();
|
|
1227
|
+
const k2AtK1K2 = (side) => docK1K2.of(k2).of(side).expr();
|
|
1228
|
+
const k1IdK1K2 = (side) => docK1K2.of(k1).of(side).of('_id').expr();
|
|
1229
|
+
const k2IdK1K2 = (side) => docK1K2.of(k2).of(side).of('_id').expr();
|
|
1230
|
+
const completeId = (side) => joinIdOf(k, k1, k1IdK1K2(side), k2IdK1K2(side));
|
|
1231
|
+
const rowK1K2 = (side) => rowOf(completeId(side), k1AtK1K2(side), k2AtK1K2(side));
|
|
1232
|
+
const liftRowId = $replaceWith_(mergeObjects(root().expr(), field({
|
|
1233
|
+
_id: [
|
|
1234
|
+
'_id',
|
|
1235
|
+
$ifNull(root()
|
|
1236
|
+
.of('before')
|
|
1237
|
+
.of('_id')
|
|
1238
|
+
.expr(), root()
|
|
1239
|
+
.of('after')
|
|
1240
|
+
.of('_id')
|
|
1241
|
+
.expr(), root().of('_id').expr()),
|
|
1242
|
+
],
|
|
1243
|
+
})));
|
|
1244
|
+
const padded = (side) => isPad(k2Raw(side));
|
|
1245
|
+
const emptyObj = field({});
|
|
1246
|
+
const deletedFlags = mergeObjects(ite(padded('before'), field({ before: ['before', val(true)] }), emptyObj), ite(padded('after'), field({ after: ['after', val(true)] }), emptyObj));
|
|
1247
|
+
const joinAt = (side) => join({
|
|
1248
|
+
k1: k1At(side),
|
|
1249
|
+
k2: k2At(side),
|
|
1250
|
+
rowK1K2: rowK1K2(side),
|
|
1251
|
+
rowOnK1: rowOnK1(side),
|
|
1252
|
+
rowOnK2: rowOnK2(side),
|
|
1253
|
+
k2Keep: k2Keep(side),
|
|
1254
|
+
k2Raw: k2Raw(side),
|
|
1255
|
+
k2RawK1: k2RawK1(side),
|
|
1256
|
+
k2KeepK1K2: k2KeepK1K2(side),
|
|
1257
|
+
});
|
|
1258
|
+
const joinDelta = mergeObjects(field({
|
|
1259
|
+
_id: ['_id', parentId],
|
|
1260
|
+
before: ['before', joinAt('before')],
|
|
1261
|
+
after: ['after', joinAt('after')],
|
|
1262
|
+
}), ite(or(padded('before'), padded('after')), field({ deleted: ['deleted', deletedFlags] }), emptyObj));
|
|
1263
|
+
return link()
|
|
1264
|
+
.with($replaceWith_(mergeObjects(src.expr(), deltas)))
|
|
1265
|
+
.with($unwind_(k2))
|
|
1266
|
+
.with($replaceWith_(joinDelta))
|
|
1267
|
+
.with(matchDelta())
|
|
1268
|
+
.with(liftRowId).stages;
|
|
1167
1269
|
};
|
|
1168
|
-
const
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1171
|
-
{
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1270
|
+
const noPadToNull = (k2) => k2;
|
|
1271
|
+
const neverPad = (_k2) => val(false);
|
|
1272
|
+
if (includeNull2 === null) {
|
|
1273
|
+
const padObj = field({});
|
|
1274
|
+
const padDelta = (after) => field({
|
|
1275
|
+
before: ['before', padObj],
|
|
1276
|
+
after: ['after', after],
|
|
1277
|
+
});
|
|
1278
|
+
const addedPadded = k === k1
|
|
1279
|
+
? array()
|
|
1280
|
+
: ite(and(not(k2Empty('before')), k2Empty('after')), array(padObj), added);
|
|
1281
|
+
const padToNull = (k2, keep) => ite(eqTyped(k2, field({})), nil, keep);
|
|
1282
|
+
const isPad = (k2) => ite(eqTyped(k2, field({})), val(true), val(false));
|
|
1283
|
+
const keptMatched = ite(k2Empty('before'), ite(k2Empty('after'), array(padDelta(padObj)), array(padDelta(nil))), kept);
|
|
1284
|
+
const padded = { added: addedPadded, padToNull, isPad };
|
|
1285
|
+
if (includeNull1 === null) {
|
|
1286
|
+
if (k === k1) {
|
|
1287
|
+
return unwindJoin({
|
|
1288
|
+
...padded,
|
|
1289
|
+
kept: k1Slot(padObj),
|
|
1290
|
+
join: ({ k1: k1Val, rowOnK1 }) => andAlso(k1Val, rowOnK1),
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
if (k === k2) {
|
|
1294
|
+
return unwindJoin({
|
|
1295
|
+
...padded,
|
|
1296
|
+
kept: keptMatched,
|
|
1297
|
+
join: ({ k2Raw, k2Keep, rowOnK2 }) => notObjAndAlso(k2Raw, andAlso(k2Keep, rowOnK2)),
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
return unwindJoin({
|
|
1301
|
+
...padded,
|
|
1302
|
+
kept: keptMatched,
|
|
1303
|
+
join: ({ k1: k1Val, k2RawK1, k2KeepK1K2, rowK1K2 }) => andAlso(k1Val, notObjAndAlso(k2RawK1, andAlso(k2KeepK1K2, rowK1K2))),
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
const eq2 = literalsEqaul();
|
|
1307
|
+
if (k === k1) {
|
|
1308
|
+
return unwindJoin({
|
|
1309
|
+
...padded,
|
|
1310
|
+
kept: k1Slot(padObj),
|
|
1311
|
+
join: ({ k1: k1Val, rowOnK1 }) => andAlso(k1Val, rowOnK1),
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
return unwindJoin({
|
|
1315
|
+
...padded,
|
|
1316
|
+
kept: keptMatched,
|
|
1317
|
+
join: ({ k1: k1Val, k2RawK1, k2KeepK1K2, rowK1K2 }) => andAlso(k1Val, notObjAndAlso(k2RawK1, andAlso(k2KeepK1K2, eq2.forward(rowK1K2)))),
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
if (includeNull1 === null) {
|
|
1321
|
+
const eq1 = literalsEqaul();
|
|
1322
|
+
return unwindJoin({
|
|
1323
|
+
kept,
|
|
1324
|
+
added,
|
|
1325
|
+
padToNull: noPadToNull,
|
|
1326
|
+
isPad: neverPad,
|
|
1327
|
+
join: ({ k1, k2: k2Val, k2KeepK1K2, rowK1K2, rowOnK2 }) => {
|
|
1328
|
+
return k === k2
|
|
1329
|
+
? andAlso(k2Val, rowOnK2)
|
|
1330
|
+
: andAlso(k1, andAlso(k2KeepK1K2, eq1.forward(rowK1K2)));
|
|
1223
1331
|
},
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1334
|
+
return unwindJoin({
|
|
1335
|
+
kept,
|
|
1336
|
+
added,
|
|
1337
|
+
padToNull: noPadToNull,
|
|
1338
|
+
isPad: neverPad,
|
|
1339
|
+
join: ({ k1, k2KeepK1K2, rowK1K2 }) => andAlso(k1, andAlso(k2KeepK1K2, rowK1K2)),
|
|
1340
|
+
});
|
|
1229
1341
|
};
|
|
1230
1342
|
|
|
1231
|
-
const $unwind = (k, dict, middle) => {
|
|
1343
|
+
const $unwind = (k, dict, middle = '.') => {
|
|
1344
|
+
const joinK = ['left', middle, 'right'];
|
|
1232
1345
|
return {
|
|
1233
1346
|
delta: link()
|
|
1234
1347
|
.with($replaceWithDelta(field({
|
|
@@ -1236,22 +1349,32 @@ const $unwind = (k, dict, middle) => {
|
|
|
1236
1349
|
left: ['left', root().expr()],
|
|
1237
1350
|
right: ['right', root().of(k).expr()],
|
|
1238
1351
|
})))
|
|
1239
|
-
.with($unwindDelta('left', 'right',
|
|
1352
|
+
.with($unwindDelta('left', 'right', joinK))
|
|
1240
1353
|
.with($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({
|
|
1241
1354
|
key: root().of('right').expr(),
|
|
1242
1355
|
id: root().of('_id').expr(),
|
|
1243
1356
|
}, dict)))).stages,
|
|
1244
|
-
raw:
|
|
1357
|
+
raw: (f) => link()
|
|
1358
|
+
.with($unwind1(k)(f))
|
|
1359
|
+
.with($set1(set()({
|
|
1360
|
+
_id: [
|
|
1361
|
+
'_id',
|
|
1362
|
+
to(joinIdOf(joinK, 'left', root().of('_id').expr(), root().of(k).of('_id').expr())),
|
|
1363
|
+
],
|
|
1364
|
+
}))(f)).stages,
|
|
1245
1365
|
};
|
|
1246
1366
|
};
|
|
1247
1367
|
|
|
1248
1368
|
const $lookupDelta = ({ field1, field2 }, { coll, exec, input }, k1, k2, k, includeNull1, includeNull2) => {
|
|
1249
1369
|
const omit = omitRORec();
|
|
1250
|
-
const hash = crypto$1
|
|
1251
|
-
|
|
1370
|
+
const hash = crypto$1
|
|
1371
|
+
.createHash('md5')
|
|
1372
|
+
.update(coll.collectionName + jsonCanonicalize.canonicalize(input) + jsonCanonicalize.canonicalize(exec))
|
|
1373
|
+
.digest('base64url');
|
|
1374
|
+
const normForeignKey = (f) => to($ifNull(root().of(f).of(k1).with(field1).expr(), val(hash)));
|
|
1252
1375
|
return link()
|
|
1253
1376
|
.with($replaceWithDelta(field(map1(k1, root().expr()))))
|
|
1254
|
-
.with($set_(set()({ bId: ['bId',
|
|
1377
|
+
.with($set_(set()({ bId: ['bId', normForeignKey('before')], aId: ['aId', normForeignKey('after')] })))
|
|
1255
1378
|
.with($simpleLookup_({
|
|
1256
1379
|
coll,
|
|
1257
1380
|
k: 'a',
|
|
@@ -1284,16 +1407,22 @@ const $lookupDelta = ({ field1, field2 }, { coll, exec, input }, k1, k2, k, incl
|
|
|
1284
1407
|
return $ifNull(root().of(f).expr(), field(omit.backward(mergeExpr(omit.forward(map1(k2, otherField.of(k2).expr())), map1(k1, nil)))));
|
|
1285
1408
|
})
|
|
1286
1409
|
: link().stages)
|
|
1287
|
-
.with($unwindDelta(k1, k2, k,
|
|
1410
|
+
.with($unwindDelta(k1, k2, k, includeNull1, includeNull2)).stages;
|
|
1288
1411
|
};
|
|
1289
1412
|
|
|
1290
1413
|
const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k, includeNull) => (f) => {
|
|
1291
|
-
root().of('_id').expr();
|
|
1414
|
+
const left = root().of('_id').expr();
|
|
1415
|
+
const right = root().of(k2).of('_id').expr();
|
|
1416
|
+
const keepLeft = k === 'left';
|
|
1417
|
+
const composedId = typeof k === 'string' ? right : concat(left, val(k[1]), right);
|
|
1292
1418
|
return link()
|
|
1293
1419
|
.with($simpleLookup1({
|
|
1294
1420
|
coll,
|
|
1295
1421
|
k: k2,
|
|
1296
|
-
fields: {
|
|
1422
|
+
fields: {
|
|
1423
|
+
local: field1,
|
|
1424
|
+
foreign: root().of('before').with(field2),
|
|
1425
|
+
},
|
|
1297
1426
|
vars: {},
|
|
1298
1427
|
pipeline: link()
|
|
1299
1428
|
.with(input)
|
|
@@ -1301,8 +1430,11 @@ const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k, includeNul
|
|
|
1301
1430
|
.with($replaceWith_(root().of('before').expr())).stages,
|
|
1302
1431
|
})(f))
|
|
1303
1432
|
.with($unwind1(k2, includeNull)(f))
|
|
1304
|
-
.with(
|
|
1305
|
-
).stages
|
|
1433
|
+
.with(keepLeft
|
|
1434
|
+
? link().stages
|
|
1435
|
+
: $set1(set()({
|
|
1436
|
+
_id: ['_id', to($ifNull(composedId, left))],
|
|
1437
|
+
}))(f)).stages;
|
|
1306
1438
|
};
|
|
1307
1439
|
|
|
1308
1440
|
const asBefore = (f) => f(() => root().of('before'));
|
|
@@ -1498,9 +1630,11 @@ const runCont = async (it, cb) => {
|
|
|
1498
1630
|
};
|
|
1499
1631
|
|
|
1500
1632
|
const merge = ({ lsource: L, rsource: R, }) => mergeIterators({ sources: { L, R } });
|
|
1501
|
-
const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft) => {
|
|
1633
|
+
const join = ({ lField, rField, left, right, as, toMany }, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft, middle = '.') => {
|
|
1502
1634
|
const rightJoinField = { field1: lField, field2: rField };
|
|
1503
|
-
const joinId = '
|
|
1635
|
+
const joinId = rField.str() === '_id' && toMany !== true
|
|
1636
|
+
? 'left'
|
|
1637
|
+
: ['left', middle, 'right'];
|
|
1504
1638
|
const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as, joinId, outerLeft));
|
|
1505
1639
|
const resultingSnapshot = concatTStages(leftSnapshot, joinR_Snapshot);
|
|
1506
1640
|
const dict = { [as]: 'a' };
|
|
@@ -1512,7 +1646,10 @@ const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot,
|
|
|
1512
1646
|
const leftJoinField = { field1: rField, field2: lField };
|
|
1513
1647
|
const joinL_Delta = $lookupDelta(leftJoinField, leftSnapshot, 'right', 'left', joinId, outerLeft);
|
|
1514
1648
|
const joinR_Delta = $lookupDelta(rightJoinField, rightSnapshot, 'left', 'right', joinId, undefined, outerLeft);
|
|
1515
|
-
const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({
|
|
1649
|
+
const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({
|
|
1650
|
+
a: root().of('right').expr(),
|
|
1651
|
+
b: root().of('_id').expr(),
|
|
1652
|
+
}, dictId))), stagesUntilNextLookup.delta);
|
|
1516
1653
|
const lRunnerInput = concatStages(joinR_Delta, mergeForeignIntoDoc);
|
|
1517
1654
|
const rRunnerInput = concatStages(joinL_Delta, mergeForeignIntoDoc);
|
|
1518
1655
|
const getRunner = (f, stages, final) => f.out({
|
|
@@ -1541,6 +1678,7 @@ const $lookup = (p) => (l) => $lookup1({
|
|
|
1541
1678
|
lField: p.localField,
|
|
1542
1679
|
rField: p.foreignField,
|
|
1543
1680
|
left: l(emptyDelta()),
|
|
1681
|
+
toMany: p.toMany,
|
|
1544
1682
|
});
|
|
1545
1683
|
const $outerLookup = (p) => (l) => $lookup1({
|
|
1546
1684
|
right: p.from,
|
|
@@ -1548,28 +1686,9 @@ const $outerLookup = (p) => (l) => $lookup1({
|
|
|
1548
1686
|
lField: p.localField,
|
|
1549
1687
|
rField: p.foreignField,
|
|
1550
1688
|
left: l(emptyDelta()),
|
|
1689
|
+
toMany: p.toMany,
|
|
1551
1690
|
}, null);
|
|
1552
1691
|
|
|
1553
|
-
const filterUndefined = (applyOperator) => {
|
|
1554
|
-
return (op, args) => applyOperator(op, args.filter(defined));
|
|
1555
|
-
};
|
|
1556
|
-
const combine = (op, applyOperatorToPreItems) => (...args) => {
|
|
1557
|
-
const mapToItems = applyOperatorToPreItems(op, args);
|
|
1558
|
-
return mapToItems && { raw: field => mapToItems(x => x.raw(field)) };
|
|
1559
|
-
};
|
|
1560
|
-
const all = (op, x) => x.length === 0 ? undefined : f => ({ [op]: x.map(f) });
|
|
1561
|
-
const first = (op, x) => (x.length === 1 ? f => f(x[0]) : all(op, x));
|
|
1562
|
-
const $and = combine('$and', filterUndefined(first));
|
|
1563
|
-
const $nor = combine('$nor', filterUndefined(all));
|
|
1564
|
-
const $or = combine('$or', filterUndefined(first));
|
|
1565
|
-
|
|
1566
|
-
const $matchDelta = (query) => concatStages($replaceWithDelta(ite(query, root().expr(), nil)), $match_($or(root().of('after').has($ne(null)), root().of('before').has($ne(null)))));
|
|
1567
|
-
|
|
1568
|
-
const $match = (query) => ({
|
|
1569
|
-
raw: $match1($expr(query)),
|
|
1570
|
-
delta: $matchDelta(query),
|
|
1571
|
-
});
|
|
1572
|
-
|
|
1573
1692
|
const $setCore = (updater) => ({
|
|
1574
1693
|
delta: $setDelta(updater),
|
|
1575
1694
|
raw: $set1(updater),
|
|
@@ -1590,7 +1709,10 @@ const $insertX = (out, expr, map, ext, extExpr, update = x => x) => {
|
|
|
1590
1709
|
teardown: c => c({
|
|
1591
1710
|
collection: out,
|
|
1592
1711
|
method: 'updateMany',
|
|
1593
|
-
params: [
|
|
1712
|
+
params: [
|
|
1713
|
+
filter,
|
|
1714
|
+
[{ $set: { deletedAt: '$$NOW', touchedAt: '$$CLUSTER_TIME' } }],
|
|
1715
|
+
],
|
|
1594
1716
|
}),
|
|
1595
1717
|
raw: () => {
|
|
1596
1718
|
const replacer = map(mergeObjects(expr, field(mergeExpr(extExpr, {
|
|
@@ -1614,7 +1736,10 @@ const $insertPart = (out, ext) => {
|
|
|
1614
1736
|
const extExpr = mapExact(ext, (v) => val(v));
|
|
1615
1737
|
return $insertX(out, assertNotNull(root().of('after').expr()), x => ite(eq(root().of('after').expr())(nil), field(mergeExpr(translateOmit().forward(extExpr), {
|
|
1616
1738
|
deletedAt: ['deletedAt', current],
|
|
1617
|
-
_id: [
|
|
1739
|
+
_id: [
|
|
1740
|
+
'_id',
|
|
1741
|
+
assertNotNull(root().of('before').of('_id').expr()),
|
|
1742
|
+
],
|
|
1618
1743
|
touchedAt: ['touchedAt', current],
|
|
1619
1744
|
})), x), ext, extExpr);
|
|
1620
1745
|
};
|
|
@@ -1861,6 +1986,19 @@ const actions = {
|
|
|
1861
1986
|
],
|
|
1862
1987
|
};
|
|
1863
1988
|
|
|
1989
|
+
const filterUndefined = (applyOperator) => {
|
|
1990
|
+
return (op, args) => applyOperator(op, args.filter(defined));
|
|
1991
|
+
};
|
|
1992
|
+
const combine = (op, applyOperatorToPreItems) => (...args) => {
|
|
1993
|
+
const mapToItems = applyOperatorToPreItems(op, args);
|
|
1994
|
+
return mapToItems && { raw: field => mapToItems(x => x.raw(field)) };
|
|
1995
|
+
};
|
|
1996
|
+
const all = (op, x) => x.length === 0 ? undefined : f => ({ [op]: x.map(f) });
|
|
1997
|
+
const first = (op, x) => (x.length === 1 ? f => f(x[0]) : all(op, x));
|
|
1998
|
+
const $and = combine('$and', filterUndefined(first));
|
|
1999
|
+
const $nor = combine('$nor', filterUndefined(all));
|
|
2000
|
+
const $or = combine('$or', filterUndefined(first));
|
|
2001
|
+
|
|
1864
2002
|
const previous = (ts) => new mongodb.Timestamp({ t: ts.high - 60, i: 0 });
|
|
1865
2003
|
const getFirstStages = (view, needs) => {
|
|
1866
2004
|
const { projection, hardMatch: pre, match } = view;
|
|
@@ -2393,6 +2531,7 @@ exports.gte = gte;
|
|
|
2393
2531
|
exports.inArray = inArray;
|
|
2394
2532
|
exports.isArray = isArray;
|
|
2395
2533
|
exports.ite = ite;
|
|
2534
|
+
exports.joinIdOf = joinIdOf;
|
|
2396
2535
|
exports.last = last;
|
|
2397
2536
|
exports.log = log;
|
|
2398
2537
|
exports.lt = lt;
|
|
@@ -2402,6 +2541,7 @@ exports.map1 = map1;
|
|
|
2402
2541
|
exports.mapFromPlainDateTime = mapFromPlainDateTime;
|
|
2403
2542
|
exports.mapToPlainDateTime = mapToPlainDateTime;
|
|
2404
2543
|
exports.mapVal = mapVal;
|
|
2544
|
+
exports.matchDelta = matchDelta;
|
|
2405
2545
|
exports.max = max;
|
|
2406
2546
|
exports.maxDate = maxDate;
|
|
2407
2547
|
exports.mergeExact = mergeExact;
|