ChemPal Documentation - v1.6.0
    Preparing search index...

    Function evaluateCorpusAst

    • Evaluates a corpus against an advanced (boolean) search query using the same parseSearchQueryscoreAstMatch path production suppliers take in SupplierBase.fuzzyFilterAst. Pure — performs no IO and prints nothing.

      Note the leaf gate is word presence, not similarity, so the chosen scorer only ranks survivors; fuzzyWords and threshold are what change which titles survive. compareFuzzyWords surfaces exactly that difference.

      Parameters

      • query: string

        The raw search string, which may use AND/OR/NOT/parentheses.

      • corpus: CorpusEntry[]

        The titles to evaluate, from collectCachedTitles.

      • options: AstProbeOptions = {}

        Scorer, threshold, fuzzyWords, supplier filter, and row limit.

      Returns AstProbeResult

      The parsed AST, the ranked survivors, the drops with their failed terms, and the titles whose survival depends on fuzzyWords.

      const result = evaluateCorpusAst("sodium AND NOT borohydride", corpus);
      result.astText; // => '(sodium AND NOT borohydride)'
      result.matched[0]; // => { title: "Sodium Chloride", score: 86, ... }
      result.dropped[0].failedTerms; // => ["sodium"]
      export function evaluateCorpusAst(
      query: string,
      corpus: CorpusEntry[],
      options: AstProbeOptions = {},
      ): AstProbeResult {
      const scorerName = options.scorer ?? DEFAULT_AST_SCORER;
      const threshold = options.threshold ?? DEFAULT_THRESHOLD;
      const fuzzyWords = options.fuzzyWords ?? true;
      const filtered = filterBySuppliers(corpus, options.suppliers);
      const parsed = parseSearchQuery(query);
      const evalOptions = { scorer: FUZZ_SCORERS[scorerName], threshold, fuzzyWords };

      const compare = options.compareFuzzyWords !== false;
      const inverted = { ...evalOptions, fuzzyWords: !fuzzyWords };

      const matched: ScoredEntry[] = [];
      const dropped: DroppedEntry[] = [];
      const fuzzyWordsDelta: AstProbeResult['fuzzyWordsDelta'] = [];
      for (const entry of filtered) {
      const score = scoreAstMatch(entry.title, parsed.ast, evalOptions);
      if (score === null) {
      dropped.push({ ...entry, failedTerms: explainDrop(entry.title, parsed.ast, fuzzyWords) });
      } else {
      matched.push({ ...entry, score });
      }

      if (!compare) {
      continue;
      }
      const survivesInverted = scoreAstMatch(entry.title, parsed.ast, inverted) !== null;
      if ((score !== null) === survivesInverted) {
      continue;
      }
      // Name the fuzzyWords setting that kept it, whichever pass that was.
      const keptByFuzzy = score !== null ? fuzzyWords : !fuzzyWords;
      fuzzyWordsDelta.push({ ...entry, onlyWith: keptByFuzzy ? 'fuzzyWords' : 'exact' });
      }
      matched.sort((a, b) => b.score - a.score);

      return {
      query,
      isAdvanced: parsed.isAdvanced,
      ast: parsed.ast,
      astText: renderAst(parsed.ast),
      corpusSize: filtered.length,
      scorer: scorerName,
      threshold,
      fuzzyWords,
      matched,
      dropped,
      fuzzyWordsDelta,
      };
      }