Search: parse terms filters on a single term as a term filter.
Running a terms filter on a single term is equivalent to loading a postings list into a bit set and then returning the bit set instead of reading the postings list on the fly. Close #9014
This commit is contained in:
parent
01bb02a0a4
commit
24591b3c70
|
@ -39,6 +39,7 @@ import org.elasticsearch.common.Nullable;
|
|||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.common.lucene.BytesRefs;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.common.lucene.search.MatchNoDocsFilter;
|
||||
import org.elasticsearch.common.lucene.search.RegexpFilter;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -496,11 +497,23 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
|
|||
|
||||
@Override
|
||||
public Filter termsFilter(List values, @Nullable QueryParseContext context) {
|
||||
switch (values.size()) {
|
||||
case 0:
|
||||
return new MatchNoDocsFilter();
|
||||
case 1:
|
||||
// When there is a single term, it's important to return a term filter so that
|
||||
// it can return a DocIdSet that is directly backed by a postings list, instead
|
||||
// of loading everything into a bit set and returning an iterator based on the
|
||||
// bit set
|
||||
return termFilter(values.get(0), context);
|
||||
default:
|
||||
BytesRef[] bytesRefs = new BytesRef[values.size()];
|
||||
for (int i = 0; i < bytesRefs.length; i++) {
|
||||
bytesRefs[i] = indexedValueForSearch(values.get(i));
|
||||
}
|
||||
return new TermsFilter(names.indexName(), bytesRefs);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,10 +20,15 @@
|
|||
package org.elasticsearch.index.mapper.string;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.index.IndexableFieldType;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.queries.TermFilter;
|
||||
import org.apache.lucene.queries.TermsFilter;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
|
@ -41,6 +46,7 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
|
@ -374,4 +380,18 @@ public class SimpleStringMappingTests extends ElasticsearchSingleNodeTest {
|
|||
assertTrue(mergeResult.conflicts()[0].contains("cannot enable norms"));
|
||||
}
|
||||
|
||||
public void testTermsFilter() throws Exception {
|
||||
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||
.startObject("properties").startObject("field").field("type", "string").field("index", "not_analyzed").endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
DocumentMapper defaultMapper = parser.parse(mapping);
|
||||
FieldMapper<?> mapper = defaultMapper.mappers().fullName("field").mapper();
|
||||
assertNotNull(mapper);
|
||||
assertTrue(mapper instanceof StringFieldMapper);
|
||||
assertEquals(Queries.MATCH_NO_FILTER, mapper.termsFilter(Collections.emptyList(), null));
|
||||
assertEquals(new TermFilter(new Term("field", "value")), mapper.termsFilter(Collections.singletonList("value"), null));
|
||||
assertEquals(new TermsFilter(new Term("field", "value1"), new Term("field", "value2")), mapper.termsFilter(Arrays.asList("value1", "value2"), null));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue