3939 */
4040public abstract class QueryList {
4141 protected final Block block ;
42+ protected final boolean onlySingleValues ;
4243
43- protected QueryList (Block block ) {
44+ protected QueryList (Block block , boolean onlySingleValues ) {
4445 this .block = block ;
46+ this .onlySingleValues = onlySingleValues ;
4547 }
4648
4749 /**
@@ -51,6 +53,12 @@ int getPositionCount() {
5153 return block .getPositionCount ();
5254 }
5355
56+ /**
57+ * Returns a copy of this query list that only returns queries for single-valued positions.
58+ * That is, it returns `null` queries for either multivalued or null positions.
59+ */
60+ public abstract QueryList onlySingleValues ();
61+
5462 /**
5563 * Returns the query at the given position.
5664 */
@@ -93,7 +101,7 @@ public static QueryList rawTermQueryList(MappedFieldType field, SearchExecutionC
93101 case COMPOSITE -> throw new IllegalArgumentException ("can't read values from [composite] block" );
94102 case UNKNOWN -> throw new IllegalArgumentException ("can't read values from [" + block + "]" );
95103 };
96- return new TermQueryList (field , searchExecutionContext , block , blockToJavaObject );
104+ return new TermQueryList (field , searchExecutionContext , block , false , blockToJavaObject );
97105 }
98106
99107 /**
@@ -103,7 +111,7 @@ public static QueryList rawTermQueryList(MappedFieldType field, SearchExecutionC
103111 public static QueryList ipTermQueryList (MappedFieldType field , SearchExecutionContext searchExecutionContext , BytesRefBlock block ) {
104112 BytesRef scratch = new BytesRef ();
105113 byte [] ipBytes = new byte [InetAddressPoint .BYTES ];
106- return new TermQueryList (field , searchExecutionContext , block , offset -> {
114+ return new TermQueryList (field , searchExecutionContext , block , false , offset -> {
107115 final var bytes = block .getBytesRef (offset , scratch );
108116 if (ipBytes .length != bytes .length ) {
109117 // Lucene only support 16-byte IP addresses, even IPv4 is encoded in 16 bytes
@@ -123,6 +131,7 @@ public static QueryList dateTermQueryList(MappedFieldType field, SearchExecution
123131 field ,
124132 searchExecutionContext ,
125133 block ,
134+ false ,
126135 field instanceof RangeFieldMapper .RangeFieldType rangeFieldType
127136 ? offset -> rangeFieldType .dateTimeFormatter ().formatMillis (block .getLong (offset ))
128137 : block ::getLong
@@ -133,7 +142,7 @@ public static QueryList dateTermQueryList(MappedFieldType field, SearchExecution
133142 * Returns a list of geo_shape queries for the given field and the input block.
134143 */
135144 public static QueryList geoShapeQueryList (MappedFieldType field , SearchExecutionContext searchExecutionContext , Block block ) {
136- return new GeoShapeQueryList (field , searchExecutionContext , block );
145+ return new GeoShapeQueryList (field , searchExecutionContext , block , false );
137146 }
138147
139148 private static class TermQueryList extends QueryList {
@@ -145,18 +154,27 @@ private TermQueryList(
145154 MappedFieldType field ,
146155 SearchExecutionContext searchExecutionContext ,
147156 Block block ,
157+ boolean onlySingleValues ,
148158 IntFunction <Object > blockValueReader
149159 ) {
150- super (block );
160+ super (block , onlySingleValues );
151161 this .field = field ;
152162 this .searchExecutionContext = searchExecutionContext ;
153163 this .blockValueReader = blockValueReader ;
154164 }
155165
166+ @ Override
167+ public TermQueryList onlySingleValues () {
168+ return new TermQueryList (field , searchExecutionContext , block , true , blockValueReader );
169+ }
170+
156171 @ Override
157172 Query getQuery (int position ) {
158- final int first = block .getFirstValueIndex (position );
159173 final int count = block .getValueCount (position );
174+ if (onlySingleValues && count != 1 ) {
175+ return null ;
176+ }
177+ final int first = block .getFirstValueIndex (position );
160178 return switch (count ) {
161179 case 0 -> null ;
162180 case 1 -> field .termQuery (blockValueReader .apply (first ), searchExecutionContext );
@@ -179,19 +197,32 @@ private static class GeoShapeQueryList extends QueryList {
179197 private final IntFunction <Geometry > blockValueReader ;
180198 private final IntFunction <Query > shapeQuery ;
181199
182- private GeoShapeQueryList (MappedFieldType field , SearchExecutionContext searchExecutionContext , Block block ) {
183- super (block );
200+ private GeoShapeQueryList (
201+ MappedFieldType field ,
202+ SearchExecutionContext searchExecutionContext ,
203+ Block block ,
204+ boolean onlySingleValues
205+ ) {
206+ super (block , onlySingleValues );
184207
185208 this .field = field ;
186209 this .searchExecutionContext = searchExecutionContext ;
187210 this .blockValueReader = blockToGeometry (block );
188211 this .shapeQuery = shapeQuery ();
189212 }
190213
214+ @ Override
215+ public GeoShapeQueryList onlySingleValues () {
216+ return new GeoShapeQueryList (field , searchExecutionContext , block , true );
217+ }
218+
191219 @ Override
192220 Query getQuery (int position ) {
193- final int first = block .getFirstValueIndex (position );
194221 final int count = block .getValueCount (position );
222+ if (onlySingleValues && count != 1 ) {
223+ return null ;
224+ }
225+ final int first = block .getFirstValueIndex (position );
195226 return switch (count ) {
196227 case 0 -> null ;
197228 case 1 -> shapeQuery .apply (first );
0 commit comments