Optimize `terms` queries on `ip` addresses to use a `PointInSetQuery` whenever possible. (#25669)
We can't do it in the general case because of prefix queries, but I believe this is mostly used in query strings and not in explicit `terms` queries. Closes #25667
This commit is contained in:
parent
264088f1c4
commit
78a6c3427b
|
@ -177,6 +177,30 @@ public class IpFieldMapper extends FieldMapper {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query termsQuery(List<?> values, QueryShardContext context) {
|
||||
InetAddress[] addresses = new InetAddress[values.size()];
|
||||
int i = 0;
|
||||
for (Object value : values) {
|
||||
InetAddress address;
|
||||
if (value instanceof InetAddress) {
|
||||
address = (InetAddress) value;
|
||||
} else {
|
||||
if (value instanceof BytesRef) {
|
||||
value = ((BytesRef) value).utf8ToString();
|
||||
}
|
||||
if (value.toString().contains("/")) {
|
||||
// the `terms` query contains some prefix queries, so we cannot create a set query
|
||||
// and need to fall back to a disjunction of `term` queries
|
||||
return super.termsQuery(values, context);
|
||||
}
|
||||
address = InetAddresses.forString(value.toString());
|
||||
}
|
||||
addresses[i++] = address;
|
||||
}
|
||||
return InetAddressPoint.newSetQuery(name(), addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, QueryShardContext context) {
|
||||
failIfNotIndexed();
|
||||
|
|
|
@ -19,10 +19,14 @@
|
|||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.lucene.document.InetAddressPoint;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.common.network.InetAddresses;
|
||||
|
||||
|
@ -78,6 +82,22 @@ public class IpFieldTypeTests extends FieldTypeTestCase {
|
|||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||
}
|
||||
|
||||
public void testTermsQuery() {
|
||||
MappedFieldType ft = createDefaultFieldType();
|
||||
ft.setName("field");
|
||||
|
||||
assertEquals(InetAddressPoint.newSetQuery("field", InetAddresses.forString("::2"), InetAddresses.forString("::5")),
|
||||
ft.termsQuery(Arrays.asList(InetAddresses.forString("::2"), InetAddresses.forString("::5")), null));
|
||||
assertEquals(InetAddressPoint.newSetQuery("field", InetAddresses.forString("::2"), InetAddresses.forString("::5")),
|
||||
ft.termsQuery(Arrays.asList("::2", "::5"), null));
|
||||
|
||||
// if the list includes a prefix query we fallback to a bool query
|
||||
assertEquals(new ConstantScoreQuery(new BooleanQuery.Builder()
|
||||
.add(ft.termQuery("::42", null), Occur.SHOULD)
|
||||
.add(ft.termQuery("::2/16", null), Occur.SHOULD).build()),
|
||||
ft.termsQuery(Arrays.asList("::42", "::2/16"), null));
|
||||
}
|
||||
|
||||
public void testRangeQuery() {
|
||||
MappedFieldType ft = createDefaultFieldType();
|
||||
ft.setName("field");
|
||||
|
|
Loading…
Reference in New Issue