The parsed query tree.
OR-groups, each an AND-group of phrase strings. Empty groups are omitted.
// (a AND b) OR c
extractOrGroups(ast); // [["a", "b"], ["c"]]
// a AND NOT b
extractOrGroups(ast); // [["a"]]
export function extractOrGroups(ast: SearchAst): string[][] {
switch (ast.type) {
case 'term':
return ast.value === '' ? [] : [[ast.value]];
case 'or':
return [...extractOrGroups(ast.left), ...extractOrGroups(ast.right)];
case 'and': {
const left = extractOrGroups(ast.left);
const right = extractOrGroups(ast.right);
if (left.length === 0) return right;
if (right.length === 0) return left;
// Cartesian product so each combined alternative keeps its AND-group terms.
const combined: string[][] = [];
for (const l of left) {
for (const r of right) {
combined.push([...l, ...r]);
}
}
return combined;
}
case 'not':
// Negated branches yield no positive search terms.
return [];
default:
return [];
}
}
Extracts the positive (non-negated) OR-groups from a query tree as a disjunctive-normal-form-ish list: the outer array is OR-ed alternatives, and each inner array is an AND-group of phrases. Negated branches are dropped, since a keyword-only backend has nothing positive to search for in them.
Used by the keyword-only fallback (one backend request per OR-group) and as a basis for native filter construction.