Repository navigation
Conversation
When no phrase qualifies for the pf boost (single-term queries, q=*:*), the pf sub-parser returns an empty BooleanQuery that was added to the main query as a SHOULD clause, defeating the single-clause MatchAllDocsQuery optimization. Omit it, and return early when there are no clauses to build a phrase from. Likewise skip a bq that parses to an empty query, e.g. one consisting only of stopwords. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
|
🤖 AI text below 🤖 (reviewed by Nick Shanin) @ispringer I prepared an optional test-only follow-up for your current version. It adds plain-token and fielded-only checks in both Selected suites passed on your head If useful, the test-only diff is one commit directly above your current head and can be taken without rewriting history: git switch SOLR-18625
git fetch https://github.com/nick-boss-tech/solr.git pr-5303-phrase-coverage-round-2
git merge --ff-only 07328d6973c4bb3385ca6d50bfe871f8808c1550 |
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks @nick-boss-tech, took it. Fast-forwarded 07328d6 as-is, then added 901cc74 on top which collapses the four Written with Claude Code (Fable 5.1) |
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
https://issues.apache.org/jira/browse/SOLR-18625
Description
When
pfis set and no phrase qualifies for the boost (single-term queries,q=*:*), eDisMax's pf sub-parser discards every phrase viaminClauseSizeand returns an emptyBooleanQueryrather thannull. That passed thephrase != nullguard and was added to the main query as an emptySHOULDclause (visible as()in the parsed query, e.g.+(subject:wireless) ()).It did not affect scoring, but it defeated the single-clause
MatchAllDocsQueryunwrapping inExtendedDismaxQParser.parse(), soq=*:*withpfset scored aBooleanQueryover every doc instead of reaching Solr'sMatchAllDocsQueryfast paths.The same happens with
bq: a boost query consisting only of stopwords (e.g.bq=text:a) parses to an emptyBooleanQueryand was added unchecked, with the same effect onq=*:*.Split out from #4652 (closed), where the pf part was agreed to be safe on its own; the bq part is the same fix applied to the other path that can add an empty clause.
Solution
In
addShingledPhraseQueries:q=subject:foo), avoiding creating a sub-parser and analyzing an empty phrase per pf slop group.In
getBoostQueries, skip a boost query that parses to an empty query.No ranking change.
Co-authored with Claude Code (Opus 5.5).
Out of scope
DisMaxQParser.addBoostQueryhas the same gap forbq(it already usesExtendedDismaxQParser.isEmptyforpfbut notbq). Left out to keep this PR focused on eDisMax; it would be a trivial follow-up if wanted.Tests
TestExtendedDismaxParser(new, each run withsow=trueandsow=false):testNoEmptyPhraseBoostClause:q=wireless→ no pf boost and no empty()clause (fails without the fix).testNoEmptyPhraseBoostClauseForFieldedQuery:q=subject:wireless→ same, exercising the no-clauses early return.testAnalyzedSingleTermKeepsPhraseBoost:q=wi-fi(WordDelimiter splits into two tokens) → phrase boost retained.testSingleTermSynonymKeepsPhraseBoost:q=gracklewithqf=id→ multi-term synonym phrase boost retained.TestExtendedDismaxParser.testMatchAllDocs(extended): now setspf,pf2,pf3and a stopword-onlybq, acrossq=*:*/q=*and bothsowvalues, and still expectsMatchAllDocsQuery(fails without the bq fix).Ran
TestExtendedDismaxParser,QueryEqualityTest,DisMaxRequestHandlerTest(all green), plus./gradlew tidyand./gradlew check -x test.Checklist
mainbranch../gradlew check.🤖 Generated with Claude Code