197 lines
7.6 KiB
JavaScript
197 lines
7.6 KiB
JavaScript
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var densify_exports = {};
|
|
__export(densify_exports, {
|
|
$densify: () => $densify
|
|
});
|
|
module.exports = __toCommonJS(densify_exports);
|
|
var import_core = require("../../core");
|
|
var import_lazy = require("../../lazy");
|
|
var import_types = require("../../types");
|
|
var import_util = require("../../util");
|
|
var import_dateAdd = require("../expression/date/dateAdd");
|
|
var import_sort = require("./sort");
|
|
const EMPTY_OBJECT = Object.freeze({});
|
|
const $densify = (collection, expr, options) => {
|
|
const { step, bounds, unit } = expr.range;
|
|
if (unit) {
|
|
(0, import_util.assert)(import_types.TIME_UNITS.includes(unit), "");
|
|
(0, import_util.assert)(
|
|
Number.isInteger(step) && step > 0,
|
|
"The step parameter in a range statement must be a whole number when densifying a date range."
|
|
);
|
|
} else {
|
|
(0, import_util.assert)(
|
|
(0, import_util.isNumber)(step) && step > 0,
|
|
"The step parameter in a range statement must be a strictly positive numeric value."
|
|
);
|
|
}
|
|
if ((0, import_util.isArray)(bounds)) {
|
|
(0, import_util.assert)(
|
|
!!bounds && bounds.length === 2,
|
|
"A bounding array in a range statement must have exactly two elements."
|
|
);
|
|
(0, import_util.assert)(
|
|
(bounds.every(import_util.isNumber) || bounds.every(import_util.isDate)) && bounds[0] < bounds[1],
|
|
"A bounding array must be an ascending array of either two dates or two numbers."
|
|
);
|
|
(0, import_util.assert)(
|
|
unit && !bounds.some(import_util.isNumber),
|
|
"Numeric bounds may not have unit parameter."
|
|
);
|
|
}
|
|
if (expr.partitionByFields) {
|
|
(0, import_util.assert)(
|
|
(0, import_util.isArray)(expr.partitionByFields),
|
|
"$densify: `partitionByFields` must be an array of strings"
|
|
);
|
|
}
|
|
collection = (0, import_sort.$sort)(collection, { [expr.field]: 1 }, options);
|
|
const nilOptions = import_core.ComputeOptions.init(options, null);
|
|
const computeNextValue = (value) => {
|
|
return (0, import_util.isNumber)(value) ? value + step : (0, import_dateAdd.$dateAdd)(
|
|
EMPTY_OBJECT,
|
|
{ startDate: value, unit, amount: step },
|
|
nilOptions
|
|
);
|
|
};
|
|
const isValidUnit = !!unit && import_types.TIME_UNITS.includes(unit);
|
|
const getFieldValue = (o) => {
|
|
const v = (0, import_util.resolve)(o, expr.field);
|
|
if ((0, import_util.isNil)(v)) return v;
|
|
if ((0, import_util.isNumber)(v)) {
|
|
(0, import_util.assert)(
|
|
!isValidUnit,
|
|
"$densify: Encountered non-date value in collection when step has a date unit."
|
|
);
|
|
} else if ((0, import_util.isDate)(v)) {
|
|
(0, import_util.assert)(
|
|
isValidUnit,
|
|
"$densify: Encountered date value in collection when step does not have a date unit."
|
|
);
|
|
} else {
|
|
(0, import_util.assert)(false, "$densify: Densify field type must be numeric or a date");
|
|
}
|
|
return v;
|
|
};
|
|
const peekItem = new Array();
|
|
const nilFieldsIterator = (0, import_lazy.Lazy)(() => {
|
|
const item = collection.next();
|
|
const fieldValue = getFieldValue(item.value);
|
|
if ((0, import_util.isNil)(fieldValue)) return item;
|
|
peekItem.push(item);
|
|
return { done: true };
|
|
});
|
|
const nextDensifyValueMap = import_util.ValueMap.init(
|
|
options.hashFunction
|
|
);
|
|
const [lower, upper] = (0, import_util.isArray)(bounds) ? bounds : [bounds, bounds];
|
|
let maxFieldValue = void 0;
|
|
const updateMaxFieldValue = (value) => {
|
|
maxFieldValue = maxFieldValue === void 0 || maxFieldValue < value ? value : maxFieldValue;
|
|
};
|
|
const rootKey = [];
|
|
const densifyIterator = (0, import_lazy.Lazy)(() => {
|
|
const item = peekItem.length > 0 ? peekItem.pop() : collection.next();
|
|
if (item.done) return item;
|
|
let partitionKey = rootKey;
|
|
if ((0, import_util.isArray)(expr.partitionByFields)) {
|
|
partitionKey = expr.partitionByFields.map(
|
|
(k) => (0, import_util.resolve)(item.value, k)
|
|
);
|
|
(0, import_util.assert)(
|
|
partitionKey.every(import_util.isString),
|
|
"$densify: Partition fields must evaluate to string values."
|
|
);
|
|
}
|
|
(0, import_util.assert)((0, import_util.isObject)(item.value), "$densify: collection must contain documents");
|
|
const itemValue = getFieldValue(item.value);
|
|
if (!nextDensifyValueMap.has(partitionKey)) {
|
|
if (lower == "full") {
|
|
if (!nextDensifyValueMap.has(rootKey)) {
|
|
nextDensifyValueMap.set(rootKey, itemValue);
|
|
}
|
|
nextDensifyValueMap.set(partitionKey, nextDensifyValueMap.get(rootKey));
|
|
} else if (lower == "partition") {
|
|
nextDensifyValueMap.set(partitionKey, itemValue);
|
|
} else {
|
|
nextDensifyValueMap.set(partitionKey, lower);
|
|
}
|
|
}
|
|
const densifyValue = nextDensifyValueMap.get(partitionKey);
|
|
if (
|
|
// current item field value is lower than current densify value.
|
|
itemValue <= densifyValue || // range value equals or exceeds upper bound
|
|
upper != "full" && upper != "partition" && densifyValue >= upper
|
|
) {
|
|
if (densifyValue <= itemValue) {
|
|
nextDensifyValueMap.set(partitionKey, computeNextValue(densifyValue));
|
|
}
|
|
updateMaxFieldValue(itemValue);
|
|
return item;
|
|
}
|
|
nextDensifyValueMap.set(partitionKey, computeNextValue(densifyValue));
|
|
updateMaxFieldValue(densifyValue);
|
|
const denseObj = { [expr.field]: densifyValue };
|
|
if (partitionKey) {
|
|
partitionKey.forEach((v, i) => {
|
|
denseObj[expr.partitionByFields[i]] = v;
|
|
});
|
|
}
|
|
peekItem.push(item);
|
|
return { done: false, value: denseObj };
|
|
});
|
|
if (lower !== "full") return (0, import_lazy.concat)(nilFieldsIterator, densifyIterator);
|
|
let paritionIndex = -1;
|
|
let partitionKeysSet = void 0;
|
|
const fullBoundsIterator = (0, import_lazy.Lazy)(() => {
|
|
if (paritionIndex === -1) {
|
|
const fullDensifyValue = nextDensifyValueMap.get(rootKey);
|
|
nextDensifyValueMap.delete(rootKey);
|
|
partitionKeysSet = Array.from(nextDensifyValueMap.keys());
|
|
if (partitionKeysSet.length === 0) {
|
|
partitionKeysSet.push(rootKey);
|
|
nextDensifyValueMap.set(rootKey, fullDensifyValue);
|
|
}
|
|
paritionIndex++;
|
|
}
|
|
do {
|
|
const partitionKey = partitionKeysSet[paritionIndex];
|
|
const partitionMaxValue = nextDensifyValueMap.get(partitionKey);
|
|
if (partitionMaxValue < maxFieldValue) {
|
|
nextDensifyValueMap.set(
|
|
partitionKey,
|
|
computeNextValue(partitionMaxValue)
|
|
);
|
|
const denseObj = { [expr.field]: partitionMaxValue };
|
|
partitionKey.forEach((v, i) => {
|
|
denseObj[expr.partitionByFields[i]] = v;
|
|
});
|
|
return { done: false, value: denseObj };
|
|
}
|
|
paritionIndex++;
|
|
} while (paritionIndex < partitionKeysSet.length);
|
|
return { done: true };
|
|
});
|
|
return (0, import_lazy.concat)(nilFieldsIterator, densifyIterator, fullBoundsIterator);
|
|
};
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
$densify
|
|
});
|