@@ -143,7 +143,7 @@ static Result analyze(Query query, Version indexVersion) {
143
143
}
144
144
145
145
private static BiFunction <Query , Version , Result > matchNoDocsQuery () {
146
- return (query , version ) -> new Result (true , Collections .emptySet (), 1 );
146
+ return (query , version ) -> new Result (true , Collections .emptySet (), 0 );
147
147
}
148
148
149
149
private static BiFunction <Query , Version , Result > matchAllDocsQuery () {
@@ -179,36 +179,36 @@ private static BiFunction<Query, Version, Result> termInSetQuery() {
179
179
for (BytesRef term = iterator .next (); term != null ; term = iterator .next ()) {
180
180
terms .add (new QueryExtraction (new Term (iterator .field (), term )));
181
181
}
182
- return new Result (true , terms , 1 );
182
+ return new Result (true , terms , Math . min ( 1 , terms . size ()) );
183
183
};
184
184
}
185
185
186
186
private static BiFunction <Query , Version , Result > synonymQuery () {
187
187
return (query , version ) -> {
188
188
Set <QueryExtraction > terms = ((SynonymQuery ) query ).getTerms ().stream ().map (QueryExtraction ::new ).collect (toSet ());
189
- return new Result (true , terms , 1 );
189
+ return new Result (true , terms , Math . min ( 1 , terms . size ()) );
190
190
};
191
191
}
192
192
193
193
private static BiFunction <Query , Version , Result > commonTermsQuery () {
194
194
return (query , version ) -> {
195
195
Set <QueryExtraction > terms = ((CommonTermsQuery ) query ).getTerms ().stream ().map (QueryExtraction ::new ).collect (toSet ());
196
- return new Result (false , terms , 1 );
196
+ return new Result (false , terms , Math . min ( 1 , terms . size ()) );
197
197
};
198
198
}
199
199
200
200
private static BiFunction <Query , Version , Result > blendedTermQuery () {
201
201
return (query , version ) -> {
202
202
Set <QueryExtraction > terms = ((BlendedTermQuery ) query ).getTerms ().stream ().map (QueryExtraction ::new ).collect (toSet ());
203
- return new Result (true , terms , 1 );
203
+ return new Result (true , terms , Math . min ( 1 , terms . size ()) );
204
204
};
205
205
}
206
206
207
207
private static BiFunction <Query , Version , Result > phraseQuery () {
208
208
return (query , version ) -> {
209
209
Term [] terms = ((PhraseQuery ) query ).getTerms ();
210
210
if (terms .length == 0 ) {
211
- return new Result (true , Collections .emptySet (), 1 );
211
+ return new Result (true , Collections .emptySet (), 0 );
212
212
}
213
213
214
214
if (version .onOrAfter (Version .V_6_1_0 )) {
@@ -232,7 +232,7 @@ private static BiFunction<Query, Version, Result> multiPhraseQuery() {
232
232
return (query , version ) -> {
233
233
Term [][] terms = ((MultiPhraseQuery ) query ).getTermArrays ();
234
234
if (terms .length == 0 ) {
235
- return new Result (true , Collections .emptySet (), 1 );
235
+ return new Result (true , Collections .emptySet (), 0 );
236
236
}
237
237
238
238
if (version .onOrAfter (Version .V_6_1_0 )) {
@@ -297,7 +297,7 @@ private static BiFunction<Query, Version, Result> spanOrQuery() {
297
297
for (SpanQuery clause : spanOrQuery .getClauses ()) {
298
298
terms .addAll (analyze (clause , version ).extractions );
299
299
}
300
- return new Result (false , terms , 1 );
300
+ return new Result (false , terms , Math . min ( 1 , terms . size ()) );
301
301
};
302
302
}
303
303
@@ -334,6 +334,9 @@ private static BiFunction<Query, Version, Result> booleanQuery() {
334
334
numOptionalClauses ++;
335
335
}
336
336
}
337
+ if (minimumShouldMatch > numOptionalClauses ) {
338
+ return new Result (false , Collections .emptySet (), 0 );
339
+ }
337
340
if (numRequiredClauses > 0 ) {
338
341
if (version .onOrAfter (Version .V_6_1_0 )) {
339
342
UnsupportedQueryException uqe = null ;
@@ -345,7 +348,12 @@ private static BiFunction<Query, Version, Result> booleanQuery() {
345
348
// since they are completely optional.
346
349
347
350
try {
348
- results .add (analyze (clause .getQuery (), version ));
351
+ Result subResult = analyze (clause .getQuery (), version );
352
+ if (subResult .matchAllDocs == false && subResult .extractions .isEmpty ()) {
353
+ // doesn't match anything
354
+ return subResult ;
355
+ }
356
+ results .add (subResult );
349
357
} catch (UnsupportedQueryException e ) {
350
358
uqe = e ;
351
359
}
@@ -399,7 +407,12 @@ private static BiFunction<Query, Version, Result> booleanQuery() {
399
407
}
400
408
}
401
409
msm += resultMsm ;
402
- verified &= result .verified ;
410
+
411
+ if (result .verified == false
412
+ // If some inner extractions are optional, the result can't be verified
413
+ || result .minimumShouldMatch < result .extractions .size ()) {
414
+ verified = false ;
415
+ }
403
416
matchAllDocs &= result .matchAllDocs ;
404
417
extractions .addAll (result .extractions );
405
418
}
@@ -491,7 +504,7 @@ private static BiFunction<Query, Version, Result> pointRangeQuery() {
491
504
// Need to check whether upper is not smaller than lower, otherwise NumericUtils.subtract(...) fails IAE
492
505
// If upper is really smaller than lower then we deal with like MatchNoDocsQuery. (verified and no extractions)
493
506
if (new BytesRef (lowerPoint ).compareTo (new BytesRef (upperPoint )) > 0 ) {
494
- return new Result (true , Collections .emptySet (), 1 );
507
+ return new Result (true , Collections .emptySet (), 0 );
495
508
}
496
509
497
510
byte [] interval = new byte [16 ];
@@ -536,7 +549,15 @@ private static Result handleDisjunction(List<Query> disjunctions, int requiredSh
536
549
for (int i = 0 ; i < disjunctions .size (); i ++) {
537
550
Query disjunct = disjunctions .get (i );
538
551
Result subResult = analyze (disjunct , version );
539
- verified &= subResult .verified ;
552
+ if (subResult .verified == false
553
+ // one of the sub queries requires more than one term to match, we can't
554
+ // verify it with a single top-level min_should_match
555
+ || subResult .minimumShouldMatch > 1
556
+ // One of the inner clauses has multiple extractions, we won't be able to
557
+ // verify it with a single top-level min_should_match
558
+ || (subResult .extractions .size () > 1 && requiredShouldClauses > 1 )) {
559
+ verified = false ;
560
+ }
540
561
if (subResult .matchAllDocs ) {
541
562
numMatchAllClauses ++;
542
563
}
@@ -682,6 +703,10 @@ static class Result {
682
703
final boolean matchAllDocs ;
683
704
684
705
Result (boolean verified , Set <QueryExtraction > extractions , int minimumShouldMatch ) {
706
+ if (minimumShouldMatch > extractions .size ()) {
707
+ throw new IllegalArgumentException ("minimumShouldMatch can't be greater than the number of extractions: "
708
+ + minimumShouldMatch + " > " + extractions .size ());
709
+ }
685
710
this .extractions = extractions ;
686
711
this .verified = verified ;
687
712
this .minimumShouldMatch = minimumShouldMatch ;
0 commit comments