88package org .elasticsearch .xpack .rank .rrf ;
99
1010import org .apache .lucene .search .ScoreDoc ;
11- import org .elasticsearch .ElasticsearchParseException ;
1211import org .elasticsearch .action .ActionRequestValidationException ;
1312import org .elasticsearch .action .ResolvedIndices ;
1413import org .elasticsearch .common .util .Maps ;
@@ -98,9 +97,6 @@ public final class RRFRetrieverBuilder extends CompoundRetrieverBuilder<RRFRetri
9897 }
9998 while (p .nextToken () != XContentParser .Token .END_ARRAY ) {
10099 String field = p .text ();
101- if (field .contains ("^" )) {
102- throw new ElasticsearchParseException ("[" + NAME + "] does not support per-field weights in [fields]" );
103- }
104100 fields .add (field );
105101 }
106102 return fields ;
@@ -147,6 +143,11 @@ public RRFRetrieverBuilder(
147143 this .fields = fields == null ? null : List .copyOf (fields );
148144 this .query = query ;
149145 this .rankConstant = rankConstant ;
146+ if (weights != null && weights .length != innerRetrievers .size ()) {
147+ throw new IllegalArgumentException (
148+ "weights array length [" + weights .length + "] must match retrievers count [" + innerRetrievers .size () + "]"
149+ );
150+ }
150151 this .weights = weights ;
151152 }
152153
@@ -304,6 +305,8 @@ protected RetrieverBuilder doRewrite(QueryRewriteContext ctx) {
304305 );
305306
306307 if (fieldsInnerRetrievers .isEmpty () == false ) {
308+ // TODO: This is a incomplete solution as it does not address other incomplete copy issues
309+ // (such as dropping the retriever name and min score)
307310 int size = fieldsInnerRetrievers .size ();
308311 List <RetrieverSource > sources = new ArrayList <>(size );
309312 float [] weights = new float [size ];
@@ -315,7 +318,8 @@ protected RetrieverBuilder doRewrite(QueryRewriteContext ctx) {
315318 rewritten = new RRFRetrieverBuilder (sources , null , null , rankWindowSize , rankConstant , weights );
316319 rewritten .getPreFilterQueryBuilders ().addAll (preFilterQueryBuilders );
317320 } else {
318- return new StandardRetrieverBuilder (new MatchNoneQueryBuilder ());
321+ // Inner retriever list can be empty when using an index wildcard pattern that doesn't match any indices
322+ rewritten = new StandardRetrieverBuilder (new MatchNoneQueryBuilder ());
319323 }
320324 }
321325
@@ -327,10 +331,8 @@ public void doToXContent(XContentBuilder builder, Params params) throws IOExcept
327331 if (innerRetrievers .isEmpty () == false ) {
328332 builder .startArray (RETRIEVERS_FIELD .getPreferredName ());
329333 for (int i = 0 ; i < innerRetrievers .size (); i ++) {
330- builder .startObject ();
331- builder .field ("retriever" , innerRetrievers .get (i ).retriever ());
332- builder .field (RRFRetrieverComponent .WEIGHT_FIELD .getPreferredName (), weights [i ]);
333- builder .endObject ();
334+ RRFRetrieverComponent component = new RRFRetrieverComponent (innerRetrievers .get (i ).retriever (), weights [i ]);
335+ component .toXContent (builder , params );
334336 }
335337 builder .endArray ();
336338 }
@@ -346,7 +348,7 @@ public void doToXContent(XContentBuilder builder, Params params) throws IOExcept
346348 builder .field (QUERY_FIELD .getPreferredName (), query );
347349 }
348350
349- builder .field (RankBuilder . RANK_WINDOW_SIZE_FIELD .getPreferredName (), rankWindowSize );
351+ builder .field (RANK_WINDOW_SIZE_FIELD .getPreferredName (), rankWindowSize );
350352 builder .field (RANK_CONSTANT_FIELD .getPreferredName (), rankConstant );
351353 if (fields == null && query == null ) {
352354 builder .startArray (WEIGHTS_FIELD .getPreferredName ());
0 commit comments