The product title to test.
The parsed query tree.
The leaf scorer, threshold, and fuzzy-word toggle.
A 0–100 relevance score, or null if the predicate fails.
const ast = { type: "or",
left: { type: "term", value: "sodium hydroxide", phrase: true },
right: { type: "term", value: "potassium carbonate", phrase: true } };
scoreAstMatch("Sodium Hydroxide 98%", ast, { scorer: ratio, threshold: 50 }); // a number
scoreAstMatch("Potassium Hydroxide", ast, { scorer: ratio, threshold: 50 }); // null
export function scoreAstMatch(
title: string,
ast: SearchAst,
options: AstEvalOptions,
): number | null {
switch (ast.type) {
case 'term':
return evaluateLeaf(title, ast.value, options);
case 'and': {
const left = scoreAstMatch(title, ast.left, options);
if (left === null) return null;
const right = scoreAstMatch(title, ast.right, options);
if (right === null) return null;
return Math.min(left, right);
}
case 'or': {
const left = scoreAstMatch(title, ast.left, options);
const right = scoreAstMatch(title, ast.right, options);
if (left === null && right === null) return null;
return Math.max(left ?? 0, right ?? 0);
}
case 'not': {
const operand = scoreAstMatch(title, ast.operand, options);
return operand === null ? options.threshold : null;
}
default:
return null;
}
}
Evaluates a product title against a SearchAst, returning a relevance score when the boolean predicate holds, or
nullwhen it doesn't (so the item is filtered out).Leaf matching is precise — every word of a phrase must be present (see
evaluateLeaf) — so the fuzzy similarity of one shared word can't pull in a different chemical. Boolean nodes combine leaf scores:andtakes the weakest required match (min),ortakes the best satisfied branch (max), andnotcontributes a neutral score equal to the threshold.