UNPKG

mingo

Version:

MongoDB query language for in-memory objects

60 lines (59 loc) 1.56 kB
import { groupBy } from "../../util"; import { $push } from "../accumulator/push"; const memo = /* @__PURE__ */ new WeakMap(); const cached = (xs) => memo.has(xs); function withMemo(collection, expr, initialize, fn) { if (!memo.has(collection)) { memo.set(collection, {}); } const data = memo.get(collection); if (!(expr.field in data)) { data[expr.field] = initialize(); } let ok = false; try { const res = fn(data[expr.field]); ok = true; return res; } finally { if (!ok) { memo.delete(collection); } else if (expr.documentNumber === collection.length) { delete data[expr.field]; if (Object.keys(data).length === 0) memo.delete(collection); } } } function rank(_, collection, expr, options, dense) { return withMemo( collection, expr, () => { const sortKey = "$" + Object.keys(expr.parentExpr.sortBy)[0]; const values = $push(collection, sortKey, options); const groups = groupBy( values, ((_2, n) => values[n]) ); let i = 0; let offset = 0; for (const key of groups.keys()) { const len = groups.get(key).length; groups.set(key, [i++, offset]); offset += len; } return { values, groups }; }, ({ values, groups }) => { if (groups.size == collection.length) return expr.documentNumber; const current = values[expr.documentNumber - 1]; const [i, n] = groups.get(current); return (dense ? i : n) + 1; } ); } export { cached, rank, withMemo };