Skip to content

[fix] return results for a query made only of negated terms - #806

Merged
asciimoo merged 1 commit into
asciimoo:masterfrom
kevin9327:fix/negated-only-query
Oct 5, 2026
Merged

asciimoo merged 1 commit into
asciimoo:masterfrom
kevin9327:fix/negated-only-query

Conversation

@kevin9327

Copy link
Copy Markdown
Contributor

A negated field filter on its own returns every other document: -title:golang lists everything whose title doesn't contain golang. A negated plain term on its own returns nothing, and neither does a query made only of negated terms:

query before after
-title:golang rust, python rust, python
-golang (none) rust, python
-"golang language" (none) rust, python
-golang -python (none) rust
language -golang rust, python rust, python

(These come from three indexed pages: go.dev with "golang language", rust-lang.org with "rust language" and python.org with "python language".)

Bleve handles a boolean query that only has must-not clauses fine; it adds a match-all as the required part. querybuilder.Build adds a required clause in two places, though:

  • With a single term that isn't field specific, it adds the base URL boost as a should clause. When the term is negated there's no must clause, so Bleve makes the should clause required, and only documents whose URL starts with golang (or with -golang, since the raw token is used) can match.
  • With several terms, it wraps the positive terms in Disjunction(Conjunction(positive terms...), phrase(full query)). When every term is negated, the conjunction is empty, so the whole disjunction depends on the phrase -golang -python matching.

The fix only adds each of those when there's a positive term to go with it (len(qs) > 0 / len(qs) == 1). Queries with at least one positive term build exactly the same query as before.

Tests:

  • TestSearchOnlyNegatedTerms in server/indexer/indexer_test.go indexes the three pages above and checks the table. On main it fails for -golang, -"golang language" and -golang -python.
  • Test_build_negated_word now also checks that -golang gets no should clause.
  • go test -race ./... passes (with a placeholder server/static/app for the embed), and golangci-lint run ./server/indexer/... reports 0 issues.

@asciimoo asciimoo left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great fix. Thank you!

@asciimoo
asciimoo merged commit 14dc26c into asciimoo:master Oct 5, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants