@noy-db/hub 0.1.0-pre.8 → 0.2.0-pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregate/index.cjs +91 -36
- package/dist/aggregate/index.cjs.map +1 -1
- package/dist/aggregate/index.d.cts +2 -2
- package/dist/aggregate/index.d.ts +2 -2
- package/dist/aggregate/index.js +16 -9
- package/dist/aggregate/index.js.map +1 -1
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +6 -6
- package/dist/blobs/index.d.ts +6 -6
- package/dist/blobs/index.js +4 -4
- package/dist/bundle/index.cjs +298 -7
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +6 -6
- package/dist/bundle/index.d.ts +6 -6
- package/dist/bundle/index.js +15 -4
- package/dist/{chunk-GOUT6DND.js → chunk-23TTQXVO.js} +173 -91
- package/dist/chunk-23TTQXVO.js.map +1 -0
- package/dist/{chunk-CIMZBAZB.js → chunk-2AXFIYHT.js} +1 -1
- package/dist/chunk-2AXFIYHT.js.map +1 -0
- package/dist/chunk-34YSDCDP.js +73 -0
- package/dist/chunk-34YSDCDP.js.map +1 -0
- package/dist/{chunk-HC7Z5EQZ.js → chunk-4TFSM22V.js} +4 -4
- package/dist/{chunk-7XBQS42M.js → chunk-537VFZTR.js} +4 -4
- package/dist/{chunk-M62XNWRA.js → chunk-5DWL3JBF.js} +2 -2
- package/dist/{chunk-RSPLI376.js → chunk-5SCJ5UEF.js} +3 -3
- package/dist/chunk-5ZGZ6HIZ.js +100 -0
- package/dist/chunk-5ZGZ6HIZ.js.map +1 -0
- package/dist/chunk-6HPZY4ON.js +291 -0
- package/dist/chunk-6HPZY4ON.js.map +1 -0
- package/dist/{chunk-WN6UK7PM.js → chunk-7H6DOO3E.js} +239 -11
- package/dist/chunk-7H6DOO3E.js.map +1 -0
- package/dist/{chunk-ACLDOTNQ.js → chunk-ADQ5MQ54.js} +275 -3
- package/dist/chunk-ADQ5MQ54.js.map +1 -0
- package/dist/chunk-CBAHB2BF.js +893 -0
- package/dist/chunk-CBAHB2BF.js.map +1 -0
- package/dist/chunk-DPMFBCV6.js +296 -0
- package/dist/chunk-DPMFBCV6.js.map +1 -0
- package/dist/chunk-DYBQG5PQ.js +34 -0
- package/dist/chunk-DYBQG5PQ.js.map +1 -0
- package/dist/{chunk-ZFKD4QMV.js → chunk-DYECX3IX.js} +3 -3
- package/dist/chunk-EGQYGYIU.js +51 -0
- package/dist/chunk-EGQYGYIU.js.map +1 -0
- package/dist/chunk-FCXOFQAJ.js +79 -0
- package/dist/chunk-FCXOFQAJ.js.map +1 -0
- package/dist/chunk-HB3Z2GCR.js +124 -0
- package/dist/chunk-HB3Z2GCR.js.map +1 -0
- package/dist/{chunk-SCZXXXU4.js → chunk-I6MX32UC.js} +7 -32
- package/dist/chunk-I6MX32UC.js.map +1 -0
- package/dist/{chunk-VQBTTTUN.js → chunk-KESP7GOK.js} +4 -4
- package/dist/{chunk-VQBTTTUN.js.map → chunk-KESP7GOK.js.map} +1 -1
- package/dist/{chunk-NXFEYLVG.js → chunk-MIQHZESA.js} +4 -3
- package/dist/{chunk-NXFEYLVG.js.map → chunk-MIQHZESA.js.map} +1 -1
- package/dist/chunk-MKSA2V7A.js +19 -0
- package/dist/chunk-MKSA2V7A.js.map +1 -0
- package/dist/{chunk-M5INGEFC.js → chunk-MRIBLZL3.js} +3 -1
- package/dist/chunk-MRIBLZL3.js.map +1 -0
- package/dist/{chunk-2WGMYBYS.js → chunk-NIOHFJPJ.js} +6 -6
- package/dist/chunk-OMLIZL2P.js +61 -0
- package/dist/chunk-OMLIZL2P.js.map +1 -0
- package/dist/{chunk-USKYUS74.js → chunk-P7EQ2S5O.js} +2 -2
- package/dist/{chunk-YVFTBQHL.js → chunk-PA6R5ZCI.js} +217 -10
- package/dist/chunk-PA6R5ZCI.js.map +1 -0
- package/dist/chunk-PEULZC6M.js +118 -0
- package/dist/chunk-PEULZC6M.js.map +1 -0
- package/dist/chunk-RD5LYKD6.js +82 -0
- package/dist/chunk-RD5LYKD6.js.map +1 -0
- package/dist/chunk-SIZWEV2Y.js +145 -0
- package/dist/chunk-SIZWEV2Y.js.map +1 -0
- package/dist/{chunk-Y4CMTMUW.js → chunk-UA4RI7OT.js} +12 -6
- package/dist/chunk-UA4RI7OT.js.map +1 -0
- package/dist/chunk-UMLVJTYV.js +20 -0
- package/dist/chunk-UMLVJTYV.js.map +1 -0
- package/dist/chunk-UZXLQCHP.js +53 -0
- package/dist/chunk-UZXLQCHP.js.map +1 -0
- package/dist/{chunk-R2ZTGEVP.js → chunk-VMIO4IXG.js} +5 -5
- package/dist/{chunk-MR4424N3.js → chunk-WCA2NROQ.js} +2 -2
- package/dist/{chunk-TDR6T5CJ.js → chunk-XGSOTWYX.js} +91 -132
- package/dist/chunk-XGSOTWYX.js.map +1 -0
- package/dist/{chunk-NPC4LFV5.js → chunk-YMYK7US4.js} +2 -2
- package/dist/{chunk-PJK6IOBC.js → chunk-YS3POABP.js} +1 -1
- package/dist/chunk-YS3POABP.js.map +1 -0
- package/dist/chunk-Z72JH4KG.js +209 -0
- package/dist/chunk-Z72JH4KG.js.map +1 -0
- package/dist/{chunk-R36SIKES.js → chunk-ZNOEIM6Y.js} +2 -2
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +6 -6
- package/dist/consent/index.d.ts +6 -6
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-IVKU7YTT.js → crypto-A7FRXYHC.js} +3 -3
- package/dist/{delegation-2DBS2EOH.js → delegation-YBA4X4JN.js} +5 -4
- package/dist/derivations/index.cjs +351 -0
- package/dist/derivations/index.cjs.map +1 -0
- package/dist/derivations/index.d.cts +71 -0
- package/dist/derivations/index.d.ts +71 -0
- package/dist/derivations/index.js +27 -0
- package/dist/{dev-unlock-BygpnIWe.d.ts → dev-unlock-D9s-loPr.d.ts} +1 -1
- package/dist/{dev-unlock-BZKx666y.d.cts → dev-unlock-DRwVSy2S.d.cts} +1 -1
- package/dist/executor-7E3VFGW7.js +11 -0
- package/dist/executor-CEWX2FQI.js +8 -0
- package/dist/executor-CEWX2FQI.js.map +1 -0
- package/dist/executor-X4SQ3ZLC.js +8 -0
- package/dist/executor-X4SQ3ZLC.js.map +1 -0
- package/dist/fanout-sidecar-VJ52RIEY.js +51 -0
- package/dist/fanout-sidecar-VJ52RIEY.js.map +1 -0
- package/dist/guards/index.cjs +315 -0
- package/dist/guards/index.cjs.map +1 -0
- package/dist/guards/index.d.cts +30 -0
- package/dist/guards/index.d.ts +30 -0
- package/dist/guards/index.js +29 -0
- package/dist/guards/index.js.map +1 -0
- package/dist/{hash-B0eU2Qv9.d.ts → hash-DXXXusyk.d.ts} +1 -1
- package/dist/{hash-CIyfmKsg.d.cts → hash-DtRih9MQ.d.cts} +1 -1
- package/dist/history/index.cjs +8 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +7 -7
- package/dist/history/index.d.ts +7 -7
- package/dist/history/index.js +6 -6
- package/dist/i18n/index.cjs +81 -0
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +6 -6
- package/dist/i18n/index.d.ts +6 -6
- package/dist/i18n/index.js +19 -6
- package/dist/i18n/index.js.map +1 -1
- package/dist/{index-Dp4tKCjX.d.ts → index-4agOpzqd.d.ts} +174 -3
- package/dist/{index-6xNpPsxR.d.cts → index-CNwA-B6-.d.ts} +303 -5
- package/dist/{index-DJTf9yxn.d.ts → index-CmVgTkqk.d.cts} +303 -5
- package/dist/{index-DsVbTDZI.d.cts → index-hdFvZkBP.d.cts} +174 -3
- package/dist/index.cjs +5929 -1089
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +207 -16
- package/dist/index.d.ts +207 -16
- package/dist/index.js +2402 -672
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs +2 -0
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.d.cts +3 -3
- package/dist/indexing/index.d.ts +3 -3
- package/dist/indexing/index.js +4 -4
- package/dist/{lazy-builder-CZVLKh0Z.d.cts → lazy-builder-C-rPfWG0.d.cts} +1 -1
- package/dist/{lazy-builder-BwEoBQZ9.d.ts → lazy-builder-Rpd-V3jP.d.ts} +1 -1
- package/dist/{ledger-UQIMMKO5.js → ledger-3TXNP47J.js} +6 -6
- package/dist/ledger-3TXNP47J.js.map +1 -0
- package/dist/materialized-views/index.cjs +837 -0
- package/dist/materialized-views/index.cjs.map +1 -0
- package/dist/materialized-views/index.d.cts +183 -0
- package/dist/materialized-views/index.d.ts +183 -0
- package/dist/materialized-views/index.js +45 -0
- package/dist/materialized-views/index.js.map +1 -0
- package/dist/overlay-views/index.cjs +359 -0
- package/dist/overlay-views/index.cjs.map +1 -0
- package/dist/overlay-views/index.d.cts +81 -0
- package/dist/overlay-views/index.d.ts +81 -0
- package/dist/overlay-views/index.js +23 -0
- package/dist/overlay-views/index.js.map +1 -0
- package/dist/periods/index.cjs +7 -1
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +6 -6
- package/dist/periods/index.d.ts +6 -6
- package/dist/periods/index.js +6 -6
- package/dist/{predicate-SBHmi6D0.d.cts → predicate-Dnu81tsS.d.cts} +25 -1
- package/dist/{predicate-SBHmi6D0.d.ts → predicate-Dnu81tsS.d.ts} +25 -1
- package/dist/{public-envelope-3QTQADDW.js → public-envelope-PY6NKFLI.js} +4 -4
- package/dist/public-envelope-PY6NKFLI.js.map +1 -0
- package/dist/query/index.cjs +302 -124
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +3 -3
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +26 -11
- package/dist/read-only-facade-ITU6L7BL.js +7 -0
- package/dist/read-only-facade-ITU6L7BL.js.map +1 -0
- package/dist/registry-3L3N3PTG.js +10 -0
- package/dist/registry-3L3N3PTG.js.map +1 -0
- package/dist/registry-O47PUPSY.js +8 -0
- package/dist/registry-O47PUPSY.js.map +1 -0
- package/dist/registry-RFGGMVNJ.js +7 -0
- package/dist/registry-RFGGMVNJ.js.map +1 -0
- package/dist/registry-WLLMODKN.js +8 -0
- package/dist/registry-WLLMODKN.js.map +1 -0
- package/dist/session/index.cjs +7 -1
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +7 -7
- package/dist/session/index.d.ts +7 -7
- package/dist/session/index.js +10 -3
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +6 -6
- package/dist/shadow/index.d.ts +6 -6
- package/dist/shadow/index.js +2 -2
- package/dist/stale-HSC5YO2O.js +13 -0
- package/dist/stale-HSC5YO2O.js.map +1 -0
- package/dist/store/index.cjs +14 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +6 -6
- package/dist/store/index.d.ts +6 -6
- package/dist/store/index.js +5 -2
- package/dist/{strategy-D-SrOLCl.d.cts → strategy-DSTrsZ8t.d.cts} +72 -19
- package/dist/{strategy-D-SrOLCl.d.ts → strategy-DSTrsZ8t.d.ts} +72 -19
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +5 -5
- package/dist/sync/index.d.ts +5 -5
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs +1554 -2
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +6 -6
- package/dist/team/index.d.ts +6 -6
- package/dist/team/index.js +76 -9
- package/dist/tx/index.cjs +296 -44
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +6 -6
- package/dist/tx/index.d.ts +6 -6
- package/dist/tx/index.js +2 -2
- package/dist/{types-DD9eKKNc.d.ts → types-C4lwMKKF.d.cts} +2771 -322
- package/dist/{types-arFMsCtn.d.cts → types-DW9RGSSs.d.ts} +2771 -322
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/with-derivation-C8LDlV7t.d.cts +13 -0
- package/dist/with-derivation-g-pGoMzL.d.ts +13 -0
- package/dist/with-guard-DWOCK4Ca.d.ts +18 -0
- package/dist/with-guard-jI1x9Z3k.d.cts +18 -0
- package/dist/with-materialized-view-DaKR-N6J.d.ts +27 -0
- package/dist/with-materialized-view-DcTx4H3j.d.cts +27 -0
- package/dist/with-overlayed-view-D-6oWAgM.d.cts +13 -0
- package/dist/with-overlayed-view-N7jYuNOS.d.ts +13 -0
- package/package.json +53 -2
- package/dist/chunk-ACLDOTNQ.js.map +0 -1
- package/dist/chunk-BTDCBVJW.js +0 -160
- package/dist/chunk-BTDCBVJW.js.map +0 -1
- package/dist/chunk-CIMZBAZB.js.map +0 -1
- package/dist/chunk-GOUT6DND.js.map +0 -1
- package/dist/chunk-M5INGEFC.js.map +0 -1
- package/dist/chunk-PJK6IOBC.js.map +0 -1
- package/dist/chunk-SCZXXXU4.js.map +0 -1
- package/dist/chunk-TDR6T5CJ.js.map +0 -1
- package/dist/chunk-TOQK4KAN.js +0 -79
- package/dist/chunk-TOQK4KAN.js.map +0 -1
- package/dist/chunk-WN6UK7PM.js.map +0 -1
- package/dist/chunk-Y4CMTMUW.js.map +0 -1
- package/dist/chunk-YVFTBQHL.js.map +0 -1
- /package/dist/{chunk-HC7Z5EQZ.js.map → chunk-4TFSM22V.js.map} +0 -0
- /package/dist/{chunk-7XBQS42M.js.map → chunk-537VFZTR.js.map} +0 -0
- /package/dist/{chunk-M62XNWRA.js.map → chunk-5DWL3JBF.js.map} +0 -0
- /package/dist/{chunk-RSPLI376.js.map → chunk-5SCJ5UEF.js.map} +0 -0
- /package/dist/{chunk-ZFKD4QMV.js.map → chunk-DYECX3IX.js.map} +0 -0
- /package/dist/{chunk-2WGMYBYS.js.map → chunk-NIOHFJPJ.js.map} +0 -0
- /package/dist/{chunk-USKYUS74.js.map → chunk-P7EQ2S5O.js.map} +0 -0
- /package/dist/{chunk-R2ZTGEVP.js.map → chunk-VMIO4IXG.js.map} +0 -0
- /package/dist/{chunk-MR4424N3.js.map → chunk-WCA2NROQ.js.map} +0 -0
- /package/dist/{chunk-NPC4LFV5.js.map → chunk-YMYK7US4.js.map} +0 -0
- /package/dist/{chunk-R36SIKES.js.map → chunk-ZNOEIM6Y.js.map} +0 -0
- /package/dist/{crypto-IVKU7YTT.js.map → crypto-A7FRXYHC.js.map} +0 -0
- /package/dist/{delegation-2DBS2EOH.js.map → delegation-YBA4X4JN.js.map} +0 -0
- /package/dist/{ledger-UQIMMKO5.js.map → derivations/index.js.map} +0 -0
- /package/dist/{public-envelope-3QTQADDW.js.map → executor-7E3VFGW7.js.map} +0 -0
package/dist/aggregate/index.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(aggregate_exports, {
|
|
|
25
25
|
GROUPBY_WARN_CARDINALITY: () => GROUPBY_WARN_CARDINALITY,
|
|
26
26
|
GroupedAggregation: () => GroupedAggregation,
|
|
27
27
|
GroupedQuery: () => GroupedQuery,
|
|
28
|
+
GroupedQueryN: () => GroupedQueryN,
|
|
28
29
|
avg: () => avg,
|
|
29
30
|
buildLiveAggregation: () => buildLiveAggregation,
|
|
30
31
|
count: () => count,
|
|
@@ -176,6 +177,18 @@ function readPath(record, path) {
|
|
|
176
177
|
return cursor;
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
// src/aggregate/canonical-key.ts
|
|
181
|
+
function canonicalGroupKey(fields, row) {
|
|
182
|
+
const sorted = [...fields].sort();
|
|
183
|
+
const parts = [];
|
|
184
|
+
for (const name of sorted) {
|
|
185
|
+
const v = row[name];
|
|
186
|
+
const serialised = v === void 0 ? "undefined" : JSON.stringify(v);
|
|
187
|
+
parts.push(`${name}=${serialised}`);
|
|
188
|
+
}
|
|
189
|
+
return parts.join("|");
|
|
190
|
+
}
|
|
191
|
+
|
|
179
192
|
// src/errors.ts
|
|
180
193
|
var NoydbError = class extends Error {
|
|
181
194
|
/** Machine-readable error code. Stable across library versions. */
|
|
@@ -209,27 +222,37 @@ var GroupCardinalityError = class extends NoydbError {
|
|
|
209
222
|
var GROUPBY_WARN_CARDINALITY = 1e4;
|
|
210
223
|
var GROUPBY_MAX_CARDINALITY = 1e5;
|
|
211
224
|
var warnedCardinalityFields = /* @__PURE__ */ new Set();
|
|
212
|
-
function warnCardinalityApproaching(
|
|
213
|
-
|
|
214
|
-
warnedCardinalityFields.
|
|
225
|
+
function warnCardinalityApproaching(fields, observed) {
|
|
226
|
+
const key = JSON.stringify([...fields].sort());
|
|
227
|
+
if (warnedCardinalityFields.has(key)) return;
|
|
228
|
+
warnedCardinalityFields.add(key);
|
|
229
|
+
const label = `[${fields.join(", ")}]`;
|
|
215
230
|
console.warn(
|
|
216
|
-
`[noy-db] .groupBy(
|
|
231
|
+
`[noy-db] .groupBy(${label}) produced ${observed} distinct groups, ${Math.round(observed / GROUPBY_MAX_CARDINALITY * 100)}% of the ${GROUPBY_MAX_CARDINALITY}-group ceiling. Narrow the query with .where() before grouping, or switch to a lower-cardinality field.`
|
|
217
232
|
);
|
|
218
233
|
}
|
|
219
234
|
function resetGroupByWarnings() {
|
|
220
235
|
warnedCardinalityFields.clear();
|
|
221
236
|
}
|
|
222
|
-
var
|
|
223
|
-
constructor(executeRecords,
|
|
237
|
+
var GroupedQueryBase = class {
|
|
238
|
+
constructor(executeRecords, fieldOrFields, upstreams, dictLabelResolver) {
|
|
224
239
|
this.executeRecords = executeRecords;
|
|
225
|
-
this.field = field;
|
|
226
240
|
this.upstreams = upstreams;
|
|
227
241
|
this.dictLabelResolver = dictLabelResolver;
|
|
242
|
+
this.fields = typeof fieldOrFields === "string" ? [fieldOrFields] : [...fieldOrFields];
|
|
228
243
|
}
|
|
229
244
|
executeRecords;
|
|
230
|
-
field;
|
|
231
245
|
upstreams;
|
|
232
246
|
dictLabelResolver;
|
|
247
|
+
/**
|
|
248
|
+
* Field set this grouped query buckets on. Stored in declaration
|
|
249
|
+
* order — the same order is preserved on every result row by
|
|
250
|
+
* `groupAndReduce`. For the single-field constructor, this is
|
|
251
|
+
* `[field]`.
|
|
252
|
+
*/
|
|
253
|
+
fields;
|
|
254
|
+
};
|
|
255
|
+
var GroupedQuery = class extends GroupedQueryBase {
|
|
233
256
|
/**
|
|
234
257
|
* Build a grouped aggregation. Returns a `GroupedAggregation`
|
|
235
258
|
* with `.run()`, `.runAsync()`, and `.live()` terminals — same shape
|
|
@@ -239,70 +262,93 @@ var GroupedQuery = class {
|
|
|
239
262
|
aggregate(spec) {
|
|
240
263
|
return new GroupedAggregation(
|
|
241
264
|
this.executeRecords,
|
|
242
|
-
this.
|
|
265
|
+
this.fields,
|
|
266
|
+
spec,
|
|
267
|
+
this.upstreams,
|
|
268
|
+
this.dictLabelResolver
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
var GroupedQueryN = class extends GroupedQueryBase {
|
|
273
|
+
aggregate(spec) {
|
|
274
|
+
return new GroupedAggregation(
|
|
275
|
+
this.executeRecords,
|
|
276
|
+
this.fields,
|
|
243
277
|
spec,
|
|
244
278
|
this.upstreams,
|
|
245
279
|
this.dictLabelResolver
|
|
246
280
|
);
|
|
247
281
|
}
|
|
248
282
|
};
|
|
249
|
-
function groupAndReduce(records,
|
|
283
|
+
function groupAndReduce(records, fieldOrFields, spec) {
|
|
284
|
+
const fields = typeof fieldOrFields === "string" ? [fieldOrFields] : fieldOrFields;
|
|
285
|
+
if (fields.length === 0) {
|
|
286
|
+
throw new Error(".groupBy() requires at least one field");
|
|
287
|
+
}
|
|
250
288
|
const buckets = /* @__PURE__ */ new Map();
|
|
289
|
+
const fieldLabel = fields.length === 1 ? fields[0] : `[${fields.join(", ")}]`;
|
|
251
290
|
for (const record of records) {
|
|
252
|
-
const
|
|
253
|
-
|
|
291
|
+
const keyValues = {};
|
|
292
|
+
for (const f of fields) {
|
|
293
|
+
keyValues[f] = readPath(record, f);
|
|
294
|
+
}
|
|
295
|
+
const dedupKey = canonicalGroupKey(fields, keyValues);
|
|
296
|
+
let bucket = buckets.get(dedupKey);
|
|
254
297
|
if (bucket === void 0) {
|
|
255
298
|
if (buckets.size >= GROUPBY_MAX_CARDINALITY) {
|
|
256
299
|
throw new GroupCardinalityError(
|
|
257
|
-
|
|
300
|
+
fieldLabel,
|
|
258
301
|
buckets.size + 1,
|
|
259
302
|
GROUPBY_MAX_CARDINALITY
|
|
260
303
|
);
|
|
261
304
|
}
|
|
262
|
-
bucket = [];
|
|
263
|
-
buckets.set(
|
|
305
|
+
bucket = { keyValues, records: [] };
|
|
306
|
+
buckets.set(dedupKey, bucket);
|
|
264
307
|
}
|
|
265
|
-
bucket.push(record);
|
|
308
|
+
bucket.records.push(record);
|
|
266
309
|
}
|
|
267
310
|
if (buckets.size >= GROUPBY_WARN_CARDINALITY) {
|
|
268
|
-
warnCardinalityApproaching(
|
|
311
|
+
warnCardinalityApproaching(fields, buckets.size);
|
|
269
312
|
}
|
|
270
|
-
const
|
|
313
|
+
const reducerKeys = Object.keys(spec);
|
|
271
314
|
const out = [];
|
|
272
|
-
for (const
|
|
315
|
+
for (const bucket of buckets.values()) {
|
|
273
316
|
const state = {};
|
|
274
|
-
for (const
|
|
275
|
-
state[
|
|
317
|
+
for (const rk of reducerKeys) {
|
|
318
|
+
state[rk] = spec[rk].init();
|
|
276
319
|
}
|
|
277
|
-
for (const record of
|
|
278
|
-
for (const
|
|
279
|
-
state[
|
|
320
|
+
for (const record of bucket.records) {
|
|
321
|
+
for (const rk of reducerKeys) {
|
|
322
|
+
state[rk] = spec[rk].step(state[rk], record);
|
|
280
323
|
}
|
|
281
324
|
}
|
|
282
|
-
const row = {
|
|
283
|
-
for (const
|
|
284
|
-
row[
|
|
325
|
+
const row = {};
|
|
326
|
+
for (const f of fields) {
|
|
327
|
+
row[f] = bucket.keyValues[f];
|
|
328
|
+
}
|
|
329
|
+
for (const rk of reducerKeys) {
|
|
330
|
+
row[rk] = spec[rk].finalize(state[rk]);
|
|
285
331
|
}
|
|
286
332
|
out.push(row);
|
|
287
333
|
}
|
|
288
334
|
return out;
|
|
289
335
|
}
|
|
290
336
|
var GroupedAggregation = class {
|
|
291
|
-
constructor(executeRecords,
|
|
337
|
+
constructor(executeRecords, fields, spec, upstreams, dictLabelResolver) {
|
|
292
338
|
this.executeRecords = executeRecords;
|
|
293
|
-
this.field = field;
|
|
294
339
|
this.spec = spec;
|
|
295
340
|
this.upstreams = upstreams;
|
|
296
341
|
this.dictLabelResolver = dictLabelResolver;
|
|
342
|
+
this.fields = typeof fields === "string" ? [fields] : [...fields];
|
|
297
343
|
}
|
|
298
344
|
executeRecords;
|
|
299
|
-
field;
|
|
300
345
|
spec;
|
|
301
346
|
upstreams;
|
|
302
347
|
dictLabelResolver;
|
|
348
|
+
fields;
|
|
303
349
|
/** Execute the query, group, reduce, and return an array of rows. */
|
|
304
350
|
run() {
|
|
305
|
-
return groupAndReduce(this.executeRecords(), this.
|
|
351
|
+
return groupAndReduce(this.executeRecords(), this.fields, this.spec);
|
|
306
352
|
}
|
|
307
353
|
/**
|
|
308
354
|
* Execute the query, group, reduce, and resolve `<field>Label` for
|
|
@@ -312,17 +358,22 @@ var GroupedAggregation = class {
|
|
|
312
358
|
*
|
|
313
359
|
* The `<field>Label` field is appended to each row. Rows whose group
|
|
314
360
|
* key has no dictionary entry get `<field>Label: undefined`.
|
|
361
|
+
*
|
|
362
|
+
* Dict-label resolution is single-field only — multi-key groupings
|
|
363
|
+
* do not produce a `<field>Label`. The resolver is only attached
|
|
364
|
+
* by the builder when `fields.length === 1`.
|
|
315
365
|
*/
|
|
316
366
|
async runAsync(opts) {
|
|
317
|
-
const rows = groupAndReduce(this.executeRecords(), this.
|
|
318
|
-
if (!opts?.locale || !this.dictLabelResolver) return rows;
|
|
367
|
+
const rows = groupAndReduce(this.executeRecords(), this.fields, this.spec);
|
|
368
|
+
if (!opts?.locale || !this.dictLabelResolver || this.fields.length !== 1) return rows;
|
|
319
369
|
const resolve = this.dictLabelResolver;
|
|
320
370
|
const locale = opts.locale;
|
|
321
371
|
const fallback = opts.fallback;
|
|
322
|
-
const
|
|
372
|
+
const field = this.fields[0];
|
|
373
|
+
const labelKey = `${field}Label`;
|
|
323
374
|
return Promise.all(
|
|
324
375
|
rows.map(async (row) => {
|
|
325
|
-
const key = row[
|
|
376
|
+
const key = row[field];
|
|
326
377
|
if (typeof key !== "string") return row;
|
|
327
378
|
const label = await resolve(key, locale, fallback);
|
|
328
379
|
return { ...row, [labelKey]: label };
|
|
@@ -346,7 +397,7 @@ var GroupedAggregation = class {
|
|
|
346
397
|
* Always call `live.stop()` when finished.
|
|
347
398
|
*/
|
|
348
399
|
live() {
|
|
349
|
-
const recompute = () => groupAndReduce(this.executeRecords(), this.
|
|
400
|
+
const recompute = () => groupAndReduce(this.executeRecords(), this.fields, this.spec);
|
|
350
401
|
return buildLiveAggregation(recompute, this.upstreams);
|
|
351
402
|
}
|
|
352
403
|
};
|
|
@@ -360,6 +411,9 @@ function withAggregate() {
|
|
|
360
411
|
groupBy(executeRecords, field, upstreams, dictLabelResolver) {
|
|
361
412
|
return new GroupedQuery(executeRecords, field, upstreams, dictLabelResolver);
|
|
362
413
|
},
|
|
414
|
+
groupByN(executeRecords, fields, upstreams) {
|
|
415
|
+
return new GroupedQueryN(executeRecords, fields, upstreams);
|
|
416
|
+
},
|
|
363
417
|
async scanAggregate(iter, spec) {
|
|
364
418
|
const collected = [];
|
|
365
419
|
for await (const record of iter) collected.push(record);
|
|
@@ -462,6 +516,7 @@ function readNumber(record, field) {
|
|
|
462
516
|
GROUPBY_WARN_CARDINALITY,
|
|
463
517
|
GroupedAggregation,
|
|
464
518
|
GroupedQuery,
|
|
519
|
+
GroupedQueryN,
|
|
465
520
|
avg,
|
|
466
521
|
buildLiveAggregation,
|
|
467
522
|
count,
|