mingo
Version:
MongoDB query language for in-memory objects
56 lines (55 loc) • 1.6 kB
JavaScript
import { computeValue } from "../../core/_internal";
import { Lazy } from "../../lazy";
import { flatten, HashMap, isNil, isString, setValue } from "../../util";
import { $lookup } from "./lookup";
const $graphLookup = (collection, expr, options) => {
const fromColl = isString(expr.from) ? options?.collectionResolver(expr.from) : expr.from;
const {
connectFromField,
connectToField,
as: asField,
maxDepth,
depthField,
restrictSearchWithMatch: matchExpr
} = expr;
const pipelineExpr = matchExpr ? { pipeline: [{ $match: matchExpr }] } : {};
return collection.map((obj) => {
const matchObj = {};
setValue(
matchObj,
connectFromField,
computeValue(obj, expr.startWith, null, options)
);
let matches = [matchObj];
let i = -1;
const map = HashMap.init();
do {
i++;
matches = flatten(
$lookup(
Lazy(matches),
{
from: fromColl,
localField: connectFromField,
foreignField: connectToField,
as: asField,
...pipelineExpr
},
options
).map((o) => o[asField]).collect()
);
const oldSize = map.size;
matches.forEach((k) => map.set(k, map.get(k) ?? i));
if (oldSize == map.size) break;
} while (isNil(maxDepth) || i < maxDepth);
const result = new Array(map.size);
let n = 0;
map.forEach((v, k) => {
result[n++] = Object.assign(depthField ? { [depthField]: v } : {}, k);
});
return { ...obj, [asField]: result };
});
};
export {
$graphLookup
};