1
0
Эх сурвалжийг харах

Correct XCombinedFieldQuery equals and hashCode (#75402)

Previously the equals and hashCode methods only compared the query terms. This
meant that queries on different fields, or with different field weights, were
considered equal.

During boolean query rewrites, duplicate clauses are removed. So because equals/
hashCode was incorrect, rewrites could accidentally drop combined_fields query
clauses.
Julie Tibshirani 4 жил өмнө
parent
commit
a40ca70de6

+ 24 - 4
server/src/main/java/org/apache/lucene/search/XCombinedFieldQuery.java

@@ -42,6 +42,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
 
@@ -134,6 +135,19 @@ public final class XCombinedFieldQuery extends Query implements Accountable {
       this.field = field;
       this.weight = weight;
     }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+      FieldAndWeight that = (FieldAndWeight) o;
+      return Float.compare(that.weight, weight) == 0 && Objects.equals(field, that.field);
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(field, weight);
+    }
   }
 
   // sorted map for fields.
@@ -199,13 +213,19 @@ public final class XCombinedFieldQuery extends Query implements Accountable {
   }
 
   @Override
-  public int hashCode() {
-    return 31 * classHash() + Arrays.hashCode(terms);
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (sameClassAs(o) == false) return false;
+    XCombinedFieldQuery that = (XCombinedFieldQuery) o;
+    return Objects.equals(fieldAndWeights, that.fieldAndWeights) && Arrays.equals(terms, that.terms);
   }
 
   @Override
-  public boolean equals(Object other) {
-    return sameClassAs(other) && Arrays.equals(terms, ((XCombinedFieldQuery) other).terms);
+  public int hashCode() {
+    int result = classHash();
+    result = 31 * result + Objects.hash(fieldAndWeights);
+    result = 31 * result + Arrays.hashCode(terms);
+    return result;
   }
 
   @Override

+ 34 - 0
server/src/test/java/org/apache/lucene/search/XCombinedFieldQueryTests.java

@@ -27,6 +27,7 @@ import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.MultiReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.BM25Similarity;
@@ -50,6 +51,39 @@ import java.util.Arrays;
  */
 public class XCombinedFieldQueryTests extends LuceneTestCase {
 
+    public void testRewrite() throws IOException {
+        IndexReader reader = new MultiReader();
+        IndexSearcher searcher = new IndexSearcher(reader);
+
+        BooleanQuery query = new BooleanQuery.Builder()
+            .add(new XCombinedFieldQuery.Builder()
+                .addField("field1")
+                .addField("field2")
+                .addTerm(new BytesRef("value"))
+                .build(), BooleanClause.Occur.SHOULD)
+            .add(new XCombinedFieldQuery.Builder()
+                .addField("field3")
+                .addField("field4")
+                .addTerm(new BytesRef("value"))
+                .build(), BooleanClause.Occur.SHOULD)
+            .build();
+        assertEquals(query, searcher.rewrite(query));
+
+        query = new BooleanQuery.Builder()
+            .add(new XCombinedFieldQuery.Builder()
+                .addField("field1", 2.0f)
+                .addField("field2")
+                .addTerm(new BytesRef("value"))
+                .build(), BooleanClause.Occur.SHOULD)
+            .add(new XCombinedFieldQuery.Builder()
+                .addField("field1", 1.3f)
+                .addField("field2")
+                .addTerm(new BytesRef("value"))
+                .build(), BooleanClause.Occur.SHOULD)
+            .build();
+        assertEquals(query, searcher.rewrite(query));
+    }
+
     public void testNormsDisabled() throws IOException {
         Directory dir = newDirectory();
         Similarity similarity = randomCompatibleSimilarity();