David Smiley created SOLR-18524:
-----------------------------------
Summary: Honor q.op only as a local-param, not as a request param
Key: SOLR-18524
URL: https://issues.apache.org/jira/browse/SOLR-18524
Project: Solr
Issue Type: Improvement
Components: query parsers
Reporter: David Smiley
h3. What
{{q.op}} (default operator for the implicit operator between clauses) should be
honored only when given as a local-param of the query it applies to, e.g.
{{q={!q.op=AND}solr rocks}} or {{fq={!edismax q.op=AND qf=title}foo bar}}. A
request-level {{q.op}} (including one set in a request handler's
defaults/appends/invariants) should no longer be consulted by query parsers.
h3. Why
*1. A request-level q.op silently changes the meaning of every {{lucene}} query
in the request, not just the user's.*
Parsers fetch it via {{QParser.getParam}}, which falls back from local params
to request params. So a request-level {{q.op=AND}} reaches every query parsed
in that request, not just {{q}}: each {{fq}}, {{facet.query}}, JSON Facet
domain filters and queries, {{bq}}/{{boost}}, nested
{{\{!parent\}}}/{{\{!join\}}} sub-queries, and so on. Readers include:
* {{LuceneQParser}} —
{{lparser.setDefaultOperator(QueryParsing.parseOP(getParam(QueryParsing.OP)))}}
* {{ComplexPhraseQParserPlugin}} — same via {{getParam}}
* {{ExtendedDismaxQParser}} and {{SimpleQParserPlugin}} —
{{SolrParams.wrapDefaults(localParams, params)}}
* {{SolrPluginUtils.parseMinShouldMatch}} — derives the {{mm}} default from it
Operators might set {{q.op=AND}} in solrconfig.xml to tune how *user* queries
match. In practice this comes with a comment like the one in a config I
maintain: {{<str name="q.op">AND</str><!-- affects filter queries too,
unfortunately :-( -->}}. That "unfortunately" is the bug.
*2. Queries generated by programs need meanings that don't depend on context.*
Filters and other non-{{q}} queries are usually built by application code, not
typed by users. The same reasoning was given for closing SOLR-15345 as Won't
Fix: {{defType}} intentionally applies only to {{q}}. Yet today the meaning of
a generated {{fq=a b}} depends on a parameter its author may not control and
may not even know is set. Defensive client code has to avoid relying on the
implicit operator everywhere: always spell out {{AND}}/{{OR}}, never emit bare
SHOULD clauses, or wrap every query in {{\{!lucene q.op=OR\}}}. Equivalent
query strings shouldn't need that care.
*3. It's inconsistent with {{defType}}.*
{{defType}} applies to {{q}} only, and {{q.op}} is closely related to it. A
user who reasonably assumes they work the same way gets surprised.
*4. It keeps producing bugs that only show up in queries it was never meant
for.*
* SOLR-12212: a parenthesized pure-NOT {{fq}} breaks under {{q.op=AND}}
* SOLR-17796: a tagged {{\{!collapse\}}} {{fq}} fails under {{q.op=AND}}
* SOLR-5161: distributed MoreLikeThis misbehaves under {{q.op=AND}}
All of these come from a request-level {{q.op}} reaching a query other than
{{q}}.
*5. The scoped alternative already exists and is the clearer form.*
Local-params make the operator part of the query it governs:
{{\{!q.op=AND\}…}}, {{\{!edismax q.op=AND …\}}}. A sub-query parser doesn't
inherit its parent's local params, so it stays truly local — it neither leaks
inward to nested queries nor outward to sibling ones.
h3. Proposal
* All request params starting with "q." (q dot) are _hoisted_ into local-params
when parsing "q" specifically, but without the "q." prefix. Actual/literal
local-params take precedence. Thus a request "q.op" becomes seen as an "op"
local-param when "q" is parsed but not anywhere else.
* Query parsers read {{op}} from their local params only: {{LuceneQParser}},
{{ComplexPhraseQParserPlugin}}, {{ExtendedDismaxQParser}},
{{SimpleQParserPlugin}}, and the {{mm}} default in
{{SolrPluginUtils.parseMinShouldMatch}}. Gate this on luceneMatchVersion.
* Update the Ref Guide (standard, edismax, dismax, and simple parser pages;
local-params page) and the major-version upgrade notes. Migration for a
handler-level default: e.g. {{q=\{!q.op=AND v=$qq\}}} with the user's query in
{{qq}}, or {{q.op}} in the local params the client already sends.
Perhaps "df" should be similar. I'm in favor of that; separate issue.
🤖 This issue was drafted with AI assistance (Claude Code).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]