Skip to content

Commit a40ca70

Browse files
authored
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.
1 parent 3d5843a commit a40ca70

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

server/src/main/java/org/apache/lucene/search/XCombinedFieldQuery.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.HashSet;
4343
import java.util.List;
4444
import java.util.Map;
45+
import java.util.Objects;
4546
import java.util.Set;
4647
import java.util.TreeMap;
4748

@@ -134,6 +135,19 @@ static class FieldAndWeight {
134135
this.field = field;
135136
this.weight = weight;
136137
}
138+
139+
@Override
140+
public boolean equals(Object o) {
141+
if (this == o) return true;
142+
if (o == null || getClass() != o.getClass()) return false;
143+
FieldAndWeight that = (FieldAndWeight) o;
144+
return Float.compare(that.weight, weight) == 0 && Objects.equals(field, that.field);
145+
}
146+
147+
@Override
148+
public int hashCode() {
149+
return Objects.hash(field, weight);
150+
}
137151
}
138152

139153
// sorted map for fields.
@@ -199,13 +213,19 @@ public String toString(String field) {
199213
}
200214

201215
@Override
202-
public int hashCode() {
203-
return 31 * classHash() + Arrays.hashCode(terms);
216+
public boolean equals(Object o) {
217+
if (this == o) return true;
218+
if (sameClassAs(o) == false) return false;
219+
XCombinedFieldQuery that = (XCombinedFieldQuery) o;
220+
return Objects.equals(fieldAndWeights, that.fieldAndWeights) && Arrays.equals(terms, that.terms);
204221
}
205222

206223
@Override
207-
public boolean equals(Object other) {
208-
return sameClassAs(other) && Arrays.equals(terms, ((XCombinedFieldQuery) other).terms);
224+
public int hashCode() {
225+
int result = classHash();
226+
result = 31 * result + Objects.hash(fieldAndWeights);
227+
result = 31 * result + Arrays.hashCode(terms);
228+
return result;
209229
}
210230

211231
@Override

server/src/test/java/org/apache/lucene/search/XCombinedFieldQueryTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.lucene.document.TextField;
2828
import org.apache.lucene.index.IndexReader;
2929
import org.apache.lucene.index.IndexWriterConfig;
30+
import org.apache.lucene.index.MultiReader;
3031
import org.apache.lucene.index.RandomIndexWriter;
3132
import org.apache.lucene.index.Term;
3233
import org.apache.lucene.search.similarities.BM25Similarity;
@@ -50,6 +51,39 @@
5051
*/
5152
public class XCombinedFieldQueryTests extends LuceneTestCase {
5253

54+
public void testRewrite() throws IOException {
55+
IndexReader reader = new MultiReader();
56+
IndexSearcher searcher = new IndexSearcher(reader);
57+
58+
BooleanQuery query = new BooleanQuery.Builder()
59+
.add(new XCombinedFieldQuery.Builder()
60+
.addField("field1")
61+
.addField("field2")
62+
.addTerm(new BytesRef("value"))
63+
.build(), BooleanClause.Occur.SHOULD)
64+
.add(new XCombinedFieldQuery.Builder()
65+
.addField("field3")
66+
.addField("field4")
67+
.addTerm(new BytesRef("value"))
68+
.build(), BooleanClause.Occur.SHOULD)
69+
.build();
70+
assertEquals(query, searcher.rewrite(query));
71+
72+
query = new BooleanQuery.Builder()
73+
.add(new XCombinedFieldQuery.Builder()
74+
.addField("field1", 2.0f)
75+
.addField("field2")
76+
.addTerm(new BytesRef("value"))
77+
.build(), BooleanClause.Occur.SHOULD)
78+
.add(new XCombinedFieldQuery.Builder()
79+
.addField("field1", 1.3f)
80+
.addField("field2")
81+
.addTerm(new BytesRef("value"))
82+
.build(), BooleanClause.Occur.SHOULD)
83+
.build();
84+
assertEquals(query, searcher.rewrite(query));
85+
}
86+
5387
public void testNormsDisabled() throws IOException {
5488
Directory dir = newDirectory();
5589
Similarity similarity = randomCompatibleSimilarity();

0 commit comments

Comments
 (0)