@omegup/msync 0.1.45 → 0.1.47
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 +41 -14
- package/index.esm.js +348 -191
- package/index.js +349 -190
- 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,10 @@ const runCont = async (it, cb) => {
|
|
|
1498
1630
|
};
|
|
1499
1631
|
|
|
1500
1632
|
const merge = ({ lsource: L, rsource: R, }) => mergeIterators({ sources: { L, R } });
|
|
1501
|
-
const join = (
|
|
1633
|
+
const join = (params, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft) => {
|
|
1634
|
+
const { lField, rField, left, right, as } = params;
|
|
1502
1635
|
const rightJoinField = { field1: lField, field2: rField };
|
|
1503
|
-
const joinId = 'left';
|
|
1636
|
+
const joinId = params.to === 'one' ? 'left' : ['left', params.middle, 'right'];
|
|
1504
1637
|
const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as, joinId, outerLeft));
|
|
1505
1638
|
const resultingSnapshot = concatTStages(leftSnapshot, joinR_Snapshot);
|
|
1506
1639
|
const dict = { [as]: 'a' };
|
|
@@ -1512,7 +1645,10 @@ const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot,
|
|
|
1512
1645
|
const leftJoinField = { field1: rField, field2: lField };
|
|
1513
1646
|
const joinL_Delta = $lookupDelta(leftJoinField, leftSnapshot, 'right', 'left', joinId, outerLeft);
|
|
1514
1647
|
const joinR_Delta = $lookupDelta(rightJoinField, rightSnapshot, 'left', 'right', joinId, undefined, outerLeft);
|
|
1515
|
-
const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({
|
|
1648
|
+
const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({
|
|
1649
|
+
a: root().of('right').expr(),
|
|
1650
|
+
b: root().of('_id').expr(),
|
|
1651
|
+
}, dictId))), stagesUntilNextLookup.delta);
|
|
1516
1652
|
const lRunnerInput = concatStages(joinR_Delta, mergeForeignIntoDoc);
|
|
1517
1653
|
const rRunnerInput = concatStages(joinL_Delta, mergeForeignIntoDoc);
|
|
1518
1654
|
const getRunner = (f, stages, final) => f.out({
|
|
@@ -1535,40 +1671,42 @@ const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot,
|
|
|
1535
1671
|
};
|
|
1536
1672
|
};
|
|
1537
1673
|
const $lookup1 = (p, outerLeft) => (input) => p.left.stages((lStages) => p.right.stages((rStages) => join(p, lStages, rStages, input, outerLeft)));
|
|
1538
|
-
const $lookup = (p) => (l) =>
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
};
|
|
1556
|
-
const
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1674
|
+
const $lookup = (p) => (l) => p.to === 'one'
|
|
1675
|
+
? $lookup1({
|
|
1676
|
+
right: p.from,
|
|
1677
|
+
as: p.as,
|
|
1678
|
+
lField: p.localField,
|
|
1679
|
+
rField: root().of('_id'),
|
|
1680
|
+
left: l(emptyDelta()),
|
|
1681
|
+
to: 'one',
|
|
1682
|
+
})
|
|
1683
|
+
: $lookup1({
|
|
1684
|
+
to: 'many',
|
|
1685
|
+
right: p.from,
|
|
1686
|
+
as: p.as,
|
|
1687
|
+
lField: p.localField,
|
|
1688
|
+
rField: p.foreignField,
|
|
1689
|
+
left: l(emptyDelta()),
|
|
1690
|
+
middle: p.middle,
|
|
1691
|
+
});
|
|
1692
|
+
const $outerLookup = (p) => (l) => p.to === 'one'
|
|
1693
|
+
? $lookup1({
|
|
1694
|
+
right: p.from,
|
|
1695
|
+
as: p.as,
|
|
1696
|
+
lField: p.localField,
|
|
1697
|
+
rField: root().of('_id'),
|
|
1698
|
+
left: l(emptyDelta()),
|
|
1699
|
+
to: 'one',
|
|
1700
|
+
}, null)
|
|
1701
|
+
: $lookup1({
|
|
1702
|
+
to: 'many',
|
|
1703
|
+
right: p.from,
|
|
1704
|
+
as: p.as,
|
|
1705
|
+
lField: p.localField,
|
|
1706
|
+
rField: p.foreignField,
|
|
1707
|
+
left: l(emptyDelta()),
|
|
1708
|
+
middle: p.middle,
|
|
1709
|
+
}, null);
|
|
1572
1710
|
|
|
1573
1711
|
const $setCore = (updater) => ({
|
|
1574
1712
|
delta: $setDelta(updater),
|
|
@@ -1590,7 +1728,10 @@ const $insertX = (out, expr, map, ext, extExpr, update = x => x) => {
|
|
|
1590
1728
|
teardown: c => c({
|
|
1591
1729
|
collection: out,
|
|
1592
1730
|
method: 'updateMany',
|
|
1593
|
-
params: [
|
|
1731
|
+
params: [
|
|
1732
|
+
filter,
|
|
1733
|
+
[{ $set: { deletedAt: '$$NOW', touchedAt: '$$CLUSTER_TIME' } }],
|
|
1734
|
+
],
|
|
1594
1735
|
}),
|
|
1595
1736
|
raw: () => {
|
|
1596
1737
|
const replacer = map(mergeObjects(expr, field(mergeExpr(extExpr, {
|
|
@@ -1614,7 +1755,10 @@ const $insertPart = (out, ext) => {
|
|
|
1614
1755
|
const extExpr = mapExact(ext, (v) => val(v));
|
|
1615
1756
|
return $insertX(out, assertNotNull(root().of('after').expr()), x => ite(eq(root().of('after').expr())(nil), field(mergeExpr(translateOmit().forward(extExpr), {
|
|
1616
1757
|
deletedAt: ['deletedAt', current],
|
|
1617
|
-
_id: [
|
|
1758
|
+
_id: [
|
|
1759
|
+
'_id',
|
|
1760
|
+
assertNotNull(root().of('before').of('_id').expr()),
|
|
1761
|
+
],
|
|
1618
1762
|
touchedAt: ['touchedAt', current],
|
|
1619
1763
|
})), x), ext, extExpr);
|
|
1620
1764
|
};
|
|
@@ -1861,6 +2005,19 @@ const actions = {
|
|
|
1861
2005
|
],
|
|
1862
2006
|
};
|
|
1863
2007
|
|
|
2008
|
+
const filterUndefined = (applyOperator) => {
|
|
2009
|
+
return (op, args) => applyOperator(op, args.filter(defined));
|
|
2010
|
+
};
|
|
2011
|
+
const combine = (op, applyOperatorToPreItems) => (...args) => {
|
|
2012
|
+
const mapToItems = applyOperatorToPreItems(op, args);
|
|
2013
|
+
return mapToItems && { raw: field => mapToItems(x => x.raw(field)) };
|
|
2014
|
+
};
|
|
2015
|
+
const all = (op, x) => x.length === 0 ? undefined : f => ({ [op]: x.map(f) });
|
|
2016
|
+
const first = (op, x) => (x.length === 1 ? f => f(x[0]) : all(op, x));
|
|
2017
|
+
const $and = combine('$and', filterUndefined(first));
|
|
2018
|
+
const $nor = combine('$nor', filterUndefined(all));
|
|
2019
|
+
const $or = combine('$or', filterUndefined(first));
|
|
2020
|
+
|
|
1864
2021
|
const previous = (ts) => new mongodb.Timestamp({ t: ts.high - 60, i: 0 });
|
|
1865
2022
|
const getFirstStages = (view, needs) => {
|
|
1866
2023
|
const { projection, hardMatch: pre, match } = view;
|
|
@@ -2393,6 +2550,7 @@ exports.gte = gte;
|
|
|
2393
2550
|
exports.inArray = inArray;
|
|
2394
2551
|
exports.isArray = isArray;
|
|
2395
2552
|
exports.ite = ite;
|
|
2553
|
+
exports.joinIdOf = joinIdOf;
|
|
2396
2554
|
exports.last = last;
|
|
2397
2555
|
exports.log = log;
|
|
2398
2556
|
exports.lt = lt;
|
|
@@ -2402,6 +2560,7 @@ exports.map1 = map1;
|
|
|
2402
2560
|
exports.mapFromPlainDateTime = mapFromPlainDateTime;
|
|
2403
2561
|
exports.mapToPlainDateTime = mapToPlainDateTime;
|
|
2404
2562
|
exports.mapVal = mapVal;
|
|
2563
|
+
exports.matchDelta = matchDelta;
|
|
2405
2564
|
exports.max = max;
|
|
2406
2565
|
exports.maxDate = maxDate;
|
|
2407
2566
|
exports.mergeExact = mergeExact;
|