mingo
Version:
MongoDB query language for in-memory objects
47 lines (46 loc) • 1.31 kB
JavaScript
import {
assert,
findInsertIndex,
has,
isArray,
isNumber,
isObject
} from "../../util";
import { errInvalidArgs } from "../expression/_internal";
import { $push } from "./push";
const $percentile = (coll, expr, options) => {
assert(
isObject(expr) && has(expr, "input", "p") && isArray(expr.p),
"$percentile expects object { input, p }"
);
const X = $push(coll, expr.input, options).filter(isNumber).sort();
const centiles = $push(expr.p, "$$CURRENT", options);
const method = expr.method || "approximate";
const output = new Array(centiles.length);
for (let i = 0; i < centiles.length; i++) {
const p = centiles[i];
if (!isNumber(p) || p < 0 || p > 1) {
return errInvalidArgs(
options.failOnError,
"$percentile 'p' must resolve to array of numbers between [0.0, 1.0]"
);
}
const r = p * (X.length - 1) + 1;
const ri = Math.floor(r);
const result = r === ri ? X[r - 1] : X[ri - 1] + r % 1 * (X[ri] - X[ri - 1]);
switch (method) {
case "exact":
output[i] = result;
break;
case "approximate": {
const pos = findInsertIndex(X, result);
output[i] = pos / X.length >= p ? X[Math.max(pos - 1, 0)] : X[pos];
break;
}
}
}
return output;
};
export {
$percentile
};