Browse Source

Fixes #16550 (thanks for the pointers @martijnvg!)

George P. Stathis 9 năm trước cách đây
mục cha
commit
b17a92c911

+ 9 - 2
core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java

@@ -26,6 +26,7 @@ import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.join.JoinUtil;
 import org.apache.lucene.search.join.ScoreMode;
+import org.apache.lucene.search.similarities.Similarity;
 import org.elasticsearch.common.io.stream.StreamInput;
 import org.elasticsearch.common.io.stream.StreamOutput;
 import org.elasticsearch.common.lucene.search.Queries;
@@ -261,7 +262,8 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
         if (maxChildren == 0) {
             maxChildren = Integer.MAX_VALUE;
         }
-        return new LateParsingQuery(parentDocMapper.typeFilter(), innerQuery, minChildren(), maxChildren, parentType, scoreMode, parentChildIndexFieldData);
+        return new LateParsingQuery(parentDocMapper.typeFilter(), innerQuery, minChildren(), maxChildren,
+                                    parentType, scoreMode, parentChildIndexFieldData, context.getSearchSimilarity());
     }
 
     final static class LateParsingQuery extends Query {
@@ -273,8 +275,11 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
         private final String parentType;
         private final ScoreMode scoreMode;
         private final ParentChildIndexFieldData parentChildIndexFieldData;
+        private final Similarity similarity;
 
-        LateParsingQuery(Query toQuery, Query innerQuery, int minChildren, int maxChildren, String parentType, ScoreMode scoreMode, ParentChildIndexFieldData parentChildIndexFieldData) {
+        LateParsingQuery(Query toQuery, Query innerQuery, int minChildren, int maxChildren,
+                         String parentType, ScoreMode scoreMode, ParentChildIndexFieldData parentChildIndexFieldData,
+                         Similarity similarity) {
             this.toQuery = toQuery;
             this.innerQuery = innerQuery;
             this.minChildren = minChildren;
@@ -282,6 +287,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
             this.parentType = parentType;
             this.scoreMode = scoreMode;
             this.parentChildIndexFieldData = parentChildIndexFieldData;
+            this.similarity = similarity;
         }
 
         @Override
@@ -294,6 +300,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
                 String joinField = ParentFieldMapper.joinField(parentType);
                 IndexSearcher indexSearcher = new IndexSearcher(reader);
                 indexSearcher.setQueryCache(null);
+                indexSearcher.setSimilarity(similarity);
                 IndexParentChildFieldData indexParentChildFieldData = parentChildIndexFieldData.loadGlobal((DirectoryReader) reader);
                 MultiDocValues.OrdinalMap ordinalMap = ParentChildIndexFieldData.getOrdinalMap(indexParentChildFieldData, parentType);
                 return JoinUtil.createJoinQuery(joinField, innerQuery, toQuery, indexSearcher, scoreMode, ordinalMap, minChildren, maxChildren);

+ 8 - 1
core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java

@@ -194,7 +194,14 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
         // wrap the query with type query
         innerQuery = Queries.filtered(innerQuery, parentDocMapper.typeFilter());
         Query childrenFilter = Queries.not(parentTypeQuery);
-        return new HasChildQueryBuilder.LateParsingQuery(childrenFilter, innerQuery, HasChildQueryBuilder.DEFAULT_MIN_CHILDREN, HasChildQueryBuilder.DEFAULT_MAX_CHILDREN, type, score ? ScoreMode.Max : ScoreMode.None, parentChildIndexFieldData);
+        return new HasChildQueryBuilder.LateParsingQuery(childrenFilter,
+                                                         innerQuery,
+                                                         HasChildQueryBuilder.DEFAULT_MIN_CHILDREN,
+                                                         HasChildQueryBuilder.DEFAULT_MAX_CHILDREN,
+                                                         type,
+                                                         score ? ScoreMode.Max : ScoreMode.None,
+                                                         parentChildIndexFieldData,
+                                                         context.getSearchSimilarity());
     }
 
     @Override

+ 48 - 0
core/src/test/java/org/elasticsearch/search/child/ChildQuerySearchIT.java

@@ -51,6 +51,7 @@ import org.hamcrest.Matchers;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -1926,4 +1927,51 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
                 QueryBuilders.hasChildQuery("child-type", new IdsQueryBuilder().addIds("child-id"))).get();
         assertSearchHits(searchResponse, "parent-id");
     }
+
+    // Tests #16550
+    public void testHasChildWithNonDefaultGlobalSimilarity() {
+      assertAcked(prepareCreate("test").setSettings(settingsBuilder().put(indexSettings())
+          .put("index.similarity.default.type", "BM25"))
+          .addMapping("parent")
+          .addMapping("child", "_parent", "type=parent", "c_field", "type=string"));
+      ensureGreen();
+
+      verifyNonDefaultSimilarity();
+    }
+
+    // Tests #16550
+    public void testHasChildWithNonDefaultFieldSimilarity() {
+      assertAcked(prepareCreate("test")
+          .addMapping("parent")
+          .addMapping("child", "_parent", "type=parent", "c_field", "type=string,similarity=BM25"));
+      ensureGreen();
+
+      verifyNonDefaultSimilarity();
+    }
+
+    // Tests #16550
+    private void verifyNonDefaultSimilarity() {
+      client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get();
+      client().prepareIndex("test", "child", "c1").setSource("c_field", "c_value").setParent("p1").get();
+      client().prepareIndex("test", "child", "c2").setSource("c_field", "c_value").setParent("p1").get();
+      refresh();
+
+      // baseline: sum of scores of matching child docs outside of has_child query
+      SearchResponse searchResponse = client().prepareSearch("test")
+          .setTypes("child")
+          .setQuery(matchQuery("c_field", "c_value"))
+          .get();
+      assertSearchHits(searchResponse, "c1", "c2");
+      Float childSum = (float) Arrays.asList(searchResponse.getHits().getHits())
+          .stream()
+          .mapToDouble(hit -> hit.getScore())
+          .sum();
+
+      // compare baseline to has_child with 'total' score_mode
+      searchResponse = client().prepareSearch("test")
+          .setQuery(hasChildQuery("child", matchQuery("c_field", "c_value")).scoreMode(ScoreMode.Total))
+          .get();
+      assertSearchHits(searchResponse, "p1");
+      assertThat(searchResponse.getHits().hits()[0].score(), equalTo(childSum));
+    }
 }