You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@solr.apache.org by "David Smiley (Jira)" <ji...@apache.org> on 2026/10/09 00:54:00 UTC

[jira] [Created] (SOLR-18524) Honor q.op only as a local-param, not as a request param

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: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org