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
|
@Override
|
||||||
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, QueryShardContext context) {
|
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, QueryShardContext context) {
|
||||||
failIfNotIndexed();
|
failIfNotIndexed();
|
||||||
|
|
|
@ -19,10 +19,14 @@
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.lucene.document.InetAddressPoint;
|
import org.apache.lucene.document.InetAddressPoint;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
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.MatchNoDocsQuery;
|
||||||
|
import org.apache.lucene.search.BooleanClause.Occur;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.common.network.InetAddresses;
|
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());
|
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() {
|
public void testRangeQuery() {
|
||||||
MappedFieldType ft = createDefaultFieldType();
|
MappedFieldType ft = createDefaultFieldType();
|
||||||
ft.setName("field");
|
ft.setName("field");
|
||||||
|
|
Loading…
Reference in New Issue