4242
4343import java .io .IOException ;
4444import java .util .ArrayList ;
45+ import java .util .HashMap ;
4546import java .util .List ;
4647import java .util .Map ;
4748import java .util .Objects ;
@@ -292,8 +293,7 @@ protected Query doToQuery(SearchExecutionContext context) throws IOException {
292293
293294 validateSimilarity (context , fields );
294295
295- Analyzer sharedAnalyzer = null ;
296- List <MultiFieldMatchQueryBuilder .FieldAndBoost > fieldsAndBoosts = new ArrayList <>();
296+ Map <Analyzer , List <FieldAndBoost >> groups = new HashMap <>();
297297 for (Map .Entry <String , Float > entry : fields .entrySet ()) {
298298 String name = entry .getKey ();
299299 MappedFieldType fieldType = context .getFieldType (name );
@@ -308,37 +308,39 @@ protected Query doToQuery(SearchExecutionContext context) throws IOException {
308308 }
309309
310310 float boost = entry .getValue () == null ? 1.0f : entry .getValue ();
311- fieldsAndBoosts .add (new MultiFieldMatchQueryBuilder .FieldAndBoost (fieldType , boost ));
312311
313- // TODO: group by analyzer.
314312 Analyzer analyzer = fieldType .getTextSearchInfo ().searchAnalyzer ();
315- if (sharedAnalyzer != null && analyzer . equals ( sharedAnalyzer ) == false ) {
316- throw new IllegalArgumentException ( "All fields in [" + NAME + "] query must have the same search analyzer" );
313+ if (groups . containsKey ( analyzer ) == false ) {
314+ groups . put ( analyzer , new ArrayList <>() );
317315 }
318- sharedAnalyzer = analyzer ;
316+ groups . get ( analyzer ). add ( new FieldAndBoost ( fieldType , boost )) ;
319317 }
320318
321- assert fieldsAndBoosts .isEmpty () == false ;
322- String placeholderFieldName = fieldsAndBoosts .get (0 ).fieldType .name ();
323- boolean canGenerateSynonymsPhraseQuery = autoGenerateSynonymsPhraseQuery ;
324- for (MultiFieldMatchQueryBuilder .FieldAndBoost fieldAndBoost : fieldsAndBoosts ) {
325- TextSearchInfo textSearchInfo = fieldAndBoost .fieldType .getTextSearchInfo ();
326- canGenerateSynonymsPhraseQuery &= textSearchInfo .hasPositions ();
327- }
319+ // TODO: For now assume we have one group.
320+ assert groups .size () == 1 ;
328321
329- MultiFieldMatchQueryBuilder .CombinedFieldsBuilder builder = new MultiFieldMatchQueryBuilder .CombinedFieldsBuilder (
330- fieldsAndBoosts ,
331- sharedAnalyzer ,
332- canGenerateSynonymsPhraseQuery ,
333- context
334- );
335- Query query = builder .createBooleanQuery (placeholderFieldName , value .toString (), operator .toBooleanClauseOccur ());
322+ List <Query > queries = new ArrayList <>();
323+ for (Map .Entry <Analyzer , List <FieldAndBoost >> group : groups .entrySet ()) {
324+ var fieldsAndBoosts = group .getValue ();
325+
326+ String placeholderFieldName = fieldsAndBoosts .get (0 ).fieldType .name ();
327+ boolean canGenerateSynonymsPhraseQuery = autoGenerateSynonymsPhraseQuery ;
328+ for (FieldAndBoost fieldAndBoost : fieldsAndBoosts ) {
329+ TextSearchInfo textSearchInfo = fieldAndBoost .fieldType .getTextSearchInfo ();
330+ canGenerateSynonymsPhraseQuery &= textSearchInfo .hasPositions ();
331+ }
336332
337- query = Queries .maybeApplyMinimumShouldMatch (query , minimumShouldMatch );
338- if (query == null ) {
339- query = zeroTermsQuery .asQuery ();
333+ var builder = new CombinedFieldsBuilder (fieldsAndBoosts , group .getKey (), canGenerateSynonymsPhraseQuery , context );
334+ Query query = builder .createBooleanQuery (placeholderFieldName , value .toString (), operator .toBooleanClauseOccur ());
335+
336+ query = Queries .maybeApplyMinimumShouldMatch (query , minimumShouldMatch );
337+ if (query == null ) {
338+ query = zeroTermsQuery .asQuery ();
339+ }
340340 }
341- return query ;
341+
342+ // TODO: combine queries.
343+ return queries .getFirst ();
342344 }
343345
344346 private static void validateSimilarity (SearchExecutionContext context , Map <String , Float > fields ) {
@@ -367,11 +369,11 @@ private static final class FieldAndBoost {
367369 }
368370
369371 private static class CombinedFieldsBuilder extends QueryBuilder {
370- private final List <MultiFieldMatchQueryBuilder . FieldAndBoost > fields ;
372+ private final List <FieldAndBoost > fields ;
371373 private final SearchExecutionContext context ;
372374
373375 CombinedFieldsBuilder (
374- List <MultiFieldMatchQueryBuilder . FieldAndBoost > fields ,
376+ List <FieldAndBoost > fields ,
375377 Analyzer analyzer ,
376378 boolean autoGenerateSynonymsPhraseQuery ,
377379 SearchExecutionContext context
@@ -411,7 +413,7 @@ protected Query newSynonymQuery(String field, TermAndBoost[] terms) {
411413 BytesRef bytes = termAndBoost .term ();
412414 query .addTerm (bytes );
413415 }
414- for (MultiFieldMatchQueryBuilder . FieldAndBoost fieldAndBoost : fields ) {
416+ for (FieldAndBoost fieldAndBoost : fields ) {
415417 MappedFieldType fieldType = fieldAndBoost .fieldType ;
416418 float fieldBoost = fieldAndBoost .boost ;
417419 query .addField (fieldType .name (), fieldBoost );
@@ -428,7 +430,7 @@ protected Query newTermQuery(Term term, float boost) {
428430 @ Override
429431 protected Query analyzePhrase (String field , TokenStream stream , int slop ) throws IOException {
430432 BooleanQuery .Builder builder = new BooleanQuery .Builder ();
431- for (MultiFieldMatchQueryBuilder . FieldAndBoost fieldAndBoost : fields ) {
433+ for (FieldAndBoost fieldAndBoost : fields ) {
432434 Query query = fieldAndBoost .fieldType .phraseQuery (stream , slop , enablePositionIncrements , context );
433435 if (fieldAndBoost .boost != 1f ) {
434436 query = new BoostQuery (query , fieldAndBoost .boost );
0 commit comments