[
https://issues.apache.org/jira/browse/SOLR-18421?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Prithvi S updated SOLR-18421:
-----------------------------
Description:
Lucene 10.4 added {{ParentsChildrenBlockJoinQuery}}: matching children of
matching parents, with an optional per-parent cap ({{childLimitPerParent}}).
Solr is already on Lucene 10.4.0 and wraps {{ToParentBlockJoinQuery}} /
{{ToChildBlockJoinQuery}} as {{!parent}} / {{!child}}, but never uses this
class.
h3. Current behavior
{{!child}} takes a *parent* query and returns *all children* of those parents
(optionally narrowed by {{childPath}}).
Child *filtering* is already possible outside the join, e.g.:
{code}
q=comments:lucene AND {!child parentPath="/"}title:solr
{code}
or via {{fq}} / {{childPath}}.
What is *not* possible today is applying a *per-parent child cap at query
time*, especially together with a child query. A Boolean
{{ToChildBlockJoinQuery}} + child query can filter children, but a limit
applied by {{ToChildBlockJoinQuery}} first is not aware of the child query, so
the intersection can be empty even when matching children exist. That is the
Lucene 10.4 motivation (https://github.com/apache/lucene/issues/14565).
The {{[child]}} transformer's {{limit}} / {{childFilter}} params are *not*
this: they decorate already-matched *parent* hits in the response. They do not
change which documents the query matches.
h3. Proposed API (backward compatible)
Keep the existing {{!child}} body as the parent query. Add optional local
params:
* {{childQuery}} — query over child documents
* {{childLimit}} — max matching children per parent (must be > 0)
{code}
q={!child parentPath="/" childQuery=$cq childLimit=2}title:solr
&cq=comments:lucene
{code}
Same params with the classic {{of}} form:
{code}
q={!child of="content_type:parent" childQuery=$cq childLimit=2}title:solr
&cq=comments:lucene
{code}
Omit *both* {{childQuery}} and {{childLimit}} → today's
{{ToChildBlockJoinQuery}} (no behavior or scoring change).
When either param is set, use {{ParentsChildrenBlockJoinQuery}}:
* missing {{childQuery}} → {{MatchAllDocsQuery}} (cap all children of matching
parents)
* missing {{childLimit}} → Lucene default {{Integer.MAX_VALUE}} (child query,
no cap)
* {{childPath}} still applies: AND it onto the child query / returned children,
same as today
* existing {{filters}} / {{excludeTags}} still apply to the *parent* clause,
same as today
Hits remain *child documents only* (same as {{!child}} today). The Lucene class
does not return parents.
h3. Scoring / stability notes
* Lucene default score is parent + child ({{Float::sum}}). Today's {{!child}}
scores from the parent query only. Do not silently switch the no-param path to
the new class.
* {{ParentsChildrenBlockJoinQuery}} is {{@lucene.experimental}}. Solr should
treat {{childQuery}} / {{childLimit}} as experimental in the ref guide until
Lucene marks the class stable (or Solr accepts the risk explicitly).
* v1 does not need to expose Lucene's custom {{scoreCombiner}}.
h3. Not in scope
* Changing {{[child]}} transformer behavior
* Returning parent+child pairs as hits
* A new query parser name
was:
Lucene 10.4 added ParentsChildrenBlockJoinQuery
(https://github.com/apache/lucene/issues/14565): match parent docs and child
docs in the same block-join query, with an optional childLimitPerParent cap.
Solr already depends on Lucene 10.4.0 (gradle/libs.versions.toml) and already
wraps ToParentBlockJoinQuery / ToChildBlockJoinQuery as \{!parent} / \{!child},
but never uses ParentsChildrenBlockJoinQuery.
*Current limitation*
{!child} takes a parent query and returns *all* children of those parents.
There is no way to:
* also filter which children match
* cap the number of matching children per parent at *query* time
The [child] transformer \{{limit}} param is response decoration of
already-matched parents, not a search-time limit.
*Proposed API (backward compatible)*
{code:java}
q=\{!child parentPath="/" childQuery=$cq childLimit=2}title:solr
&cq=comments:lucene
{code}
Omit childQuery/childLimit -> existing \{!child} behavior.
> {!child}: childQuery + per-parent childLimit via Lucene
> ParentsChildrenBlockJoinQuery
> -------------------------------------------------------------------------------------
>
> Key: SOLR-18421
> URL: https://issues.apache.org/jira/browse/SOLR-18421
> Project: Solr
> Issue Type: New Feature
> Components: query parsers
> Reporter: Prithvi S
> Priority: Major
>
> Lucene 10.4 added {{ParentsChildrenBlockJoinQuery}}: matching children of
> matching parents, with an optional per-parent cap ({{childLimitPerParent}}).
> Solr is already on Lucene 10.4.0 and wraps {{ToParentBlockJoinQuery}} /
> {{ToChildBlockJoinQuery}} as {{!parent}} / {{!child}}, but never uses this
> class.
> h3. Current behavior
> {{!child}} takes a *parent* query and returns *all children* of those parents
> (optionally narrowed by {{childPath}}).
> Child *filtering* is already possible outside the join, e.g.:
> {code}
> q=comments:lucene AND {!child parentPath="/"}title:solr
> {code}
> or via {{fq}} / {{childPath}}.
> What is *not* possible today is applying a *per-parent child cap at query
> time*, especially together with a child query. A Boolean
> {{ToChildBlockJoinQuery}} + child query can filter children, but a limit
> applied by {{ToChildBlockJoinQuery}} first is not aware of the child query,
> so the intersection can be empty even when matching children exist. That is
> the Lucene 10.4 motivation (https://github.com/apache/lucene/issues/14565).
> The {{[child]}} transformer's {{limit}} / {{childFilter}} params are *not*
> this: they decorate already-matched *parent* hits in the response. They do
> not change which documents the query matches.
> h3. Proposed API (backward compatible)
> Keep the existing {{!child}} body as the parent query. Add optional local
> params:
> * {{childQuery}} — query over child documents
> * {{childLimit}} — max matching children per parent (must be > 0)
> {code}
> q={!child parentPath="/" childQuery=$cq childLimit=2}title:solr
> &cq=comments:lucene
> {code}
> Same params with the classic {{of}} form:
> {code}
> q={!child of="content_type:parent" childQuery=$cq childLimit=2}title:solr
> &cq=comments:lucene
> {code}
> Omit *both* {{childQuery}} and {{childLimit}} → today's
> {{ToChildBlockJoinQuery}} (no behavior or scoring change).
> When either param is set, use {{ParentsChildrenBlockJoinQuery}}:
> * missing {{childQuery}} → {{MatchAllDocsQuery}} (cap all children of
> matching parents)
> * missing {{childLimit}} → Lucene default {{Integer.MAX_VALUE}} (child query,
> no cap)
> * {{childPath}} still applies: AND it onto the child query / returned
> children, same as today
> * existing {{filters}} / {{excludeTags}} still apply to the *parent* clause,
> same as today
> Hits remain *child documents only* (same as {{!child}} today). The Lucene
> class does not return parents.
> h3. Scoring / stability notes
> * Lucene default score is parent + child ({{Float::sum}}). Today's {{!child}}
> scores from the parent query only. Do not silently switch the no-param path
> to the new class.
> * {{ParentsChildrenBlockJoinQuery}} is {{@lucene.experimental}}. Solr should
> treat {{childQuery}} / {{childLimit}} as experimental in the ref guide until
> Lucene marks the class stable (or Solr accepts the risk explicitly).
> * v1 does not need to expose Lucene's custom {{scoreCombiner}}.
> h3. Not in scope
> * Changing {{[child]}} transformer behavior
> * Returning parent+child pairs as hits
> * A new query parser name
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]