Skip to content

bug: multi-term search queries OR across terms instead of narrowing (AND) #273

Description

@simonives

Problem

search(query="SuccessFactors") returns total: 41. search(query="SuccessFactors AI Talent"), a more specific, narrower-sounding query with two additional terms, returns total: 1103 — 27x more results than the single-term search.

Adding terms to a search query should narrow the result set (implicit AND, or ideally phrase-awareness), not expand it by more than an order of magnitude. The only mechanism that produces this pattern is the query being treated as an OR across all terms ("SuccessFactors" OR "AI" OR "Talent"), where "AI" and "Talent" are each independently common enough across the HR-tech corpus to explode the match count on their own.

Root cause

src/reed/graph.py:873:

prefix = (
    f"CALL QUERY_FTS_INDEX('Item', 'item_fts', $q) "
    f"WITH node AS i, score{feed_clause}{tag_clause}{where}"
)

Kuzu's QUERY_FTS_INDEX defaults to disjunctive (OR/BM25-across-any-term) matching unless called with an explicit conjunctive := true argument. That default is never overridden here, so every multi-word query silently becomes an OR query.

Impact

Defeats the actual use case for a multi-word query — using more specific language to get a smaller, more relevant result set. As implemented, adding qualifying terms makes results worse (broader and less relevant), the opposite of what a user typing a longer, more specific query expects. Surfaced via the search MCP tool (src/reed/mcp_server.py:316) and the underlying src/reed/api/search.py:45 endpoint, both of which call search_items with no way to control this.

Recommended fix

  • Default multi-term queries to conjunctive := true (implicit AND across terms) in the QUERY_FTS_INDEX call at src/reed/graph.py:873.
  • Consider supporting explicit phrase matching (quoted strings) and a documented, deliberate OR mode for when that's genuinely wanted, rather than only a global AND/OR switch.
  • Whichever default is chosen, state it explicitly in the search tool's own docstring/description (src/reed/mcp_server.py) so a caller isn't left guessing which behaviour to expect — the same gap that made this bug easy to miss until directly comparing two related queries.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions