diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java index 9a1992c39e9..76ab98a00f1 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java @@ -282,7 +282,7 @@ public class DocumentMapper implements ToXContent { this.indexAnalyzer = indexAnalyzer; this.searchAnalyzer = searchAnalyzer; - this.typeFilter = typeMapper().fieldFilter(type); + this.typeFilter = typeMapper().fieldFilter(type, null); if (rootMapper(ParentFieldMapper.class) != null) { // mark the routing field mapper as required diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java index b06bdd9bc1f..6de9a990997 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java @@ -25,6 +25,7 @@ import org.apache.lucene.document.Fieldable; import org.apache.lucene.index.Term; import org.apache.lucene.search.Filter; import org.apache.lucene.search.Query; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.util.concurrent.Immutable; import org.elasticsearch.common.util.concurrent.ThreadSafe; import org.elasticsearch.index.field.data.FieldDataType; @@ -156,7 +157,7 @@ public interface FieldMapper { /** * A field query for the specified value. */ - Query fieldQuery(String value, QueryParseContext context); + Query fieldQuery(String value, @Nullable QueryParseContext context); Query fuzzyQuery(String value, String minSim, int prefixLength, int maxExpansions); @@ -167,7 +168,7 @@ public interface FieldMapper { */ Query queryStringTermQuery(Term term); - Filter fieldFilter(String value); + Filter fieldFilter(String value, @Nullable QueryParseContext context); /** * Constructs a range query based on the mapper. diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java index 293feb825aa..9b8a92811d2 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java @@ -30,6 +30,7 @@ import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermRangeFilter; import org.apache.lucene.search.TermRangeQuery; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.search.TermFilter; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -342,10 +343,14 @@ public abstract class AbstractFieldMapper implements FieldMapper, Mapper { return false; } - @Override public Query fieldQuery(String value, QueryParseContext context) { + @Override public Query fieldQuery(String value, @Nullable QueryParseContext context) { return new TermQuery(names().createIndexNameTerm(indexedValue(value))); } + @Override public Filter fieldFilter(String value, @Nullable QueryParseContext context) { + return new TermFilter(names().createIndexNameTerm(indexedValue(value))); + } + @Override public Query fuzzyQuery(String value, String minSim, int prefixLength, int maxExpansions) { return new FuzzyQuery(names().createIndexNameTerm(indexedValue(value)), Float.parseFloat(minSim), prefixLength, maxExpansions); } @@ -354,10 +359,6 @@ public abstract class AbstractFieldMapper implements FieldMapper, Mapper { return new FuzzyQuery(names().createIndexNameTerm(value), (float) minSim, prefixLength, maxExpansions); } - @Override public Filter fieldFilter(String value) { - return new TermFilter(names().createIndexNameTerm(indexedValue(value))); - } - @Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) { return new TermRangeQuery(names.indexName(), lowerTerm == null ? null : indexedValue(lowerTerm), diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java index cdb970dd354..f488aaee250 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java @@ -156,7 +156,7 @@ public abstract class NumberFieldMapper extends AbstractFieldM * Numeric field level query are basically range queries with same value and included. That's the recommended * way to execute it. */ - @Override public Query fieldQuery(String value, QueryParseContext context) { + @Override public Query fieldQuery(String value, @Nullable QueryParseContext context) { return rangeQuery(value, value, true, true); } @@ -168,7 +168,7 @@ public abstract class NumberFieldMapper extends AbstractFieldM * Numeric field level filter are basically range queries with same value and included. That's the recommended * way to execute it. */ - @Override public Filter fieldFilter(String value) { + @Override public Filter fieldFilter(String value, @Nullable QueryParseContext context) { return rangeFilter(value, value, true, true); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java index af2c2d4e24e..0a290e4f411 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java @@ -22,7 +22,12 @@ package org.elasticsearch.index.mapper.internal; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.Fieldable; +import org.apache.lucene.search.ConstantScoreQuery; +import org.apache.lucene.search.Filter; +import org.apache.lucene.search.Query; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; @@ -34,6 +39,8 @@ import org.elasticsearch.index.mapper.MergeMappingException; import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.RootMapper; import org.elasticsearch.index.mapper.core.AbstractFieldMapper; +import org.elasticsearch.index.query.QueryParseContext; +import org.elasticsearch.index.search.UidFilter; import java.io.IOException; import java.util.Map; @@ -145,6 +152,26 @@ public class IdFieldMapper extends AbstractFieldMapper implements Intern return value; } + @Override public boolean useFieldQueryWithQueryString() { + return true; + } + + @Override public Query fieldQuery(String value, @Nullable QueryParseContext context) { + if (indexed() || context == null) { + return super.fieldQuery(value, context); + } + UidFilter filter = new UidFilter(context.mapperService().types(), ImmutableList.of(value), context.indexCache().bloomCache()); + // no need for constant score filter, since we don't cache the filter, and it always takes deletes into account + return new ConstantScoreQuery(filter); + } + + @Override public Filter fieldFilter(String value, @Nullable QueryParseContext context) { + if (indexed() || context == null) { + return super.fieldFilter(value, context); + } + return new UidFilter(context.mapperService().types(), ImmutableList.of(value), context.indexCache().bloomCache()); + } + @Override public void preParse(ParseContext context) throws IOException { if (context.sourceToParse().id() != null) { context.id(context.sourceToParse().id()); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java index ce3eaf8b68d..66f94005aaf 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java @@ -27,6 +27,7 @@ import org.apache.lucene.search.DeletionAwareConstantScoreQuery; import org.apache.lucene.search.Filter; import org.apache.lucene.search.PrefixFilter; import org.apache.lucene.search.Query; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.search.TermFilter; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -132,15 +133,15 @@ public class TypeFieldMapper extends AbstractFieldMapper implements Inte return names().createIndexNameTerm(value); } - @Override public Filter fieldFilter(String value) { + @Override public Filter fieldFilter(String value, @Nullable QueryParseContext context) { if (index == Field.Index.NO) { return new PrefixFilter(UidFieldMapper.TERM_FACTORY.createTerm(Uid.typePrefix(value))); } return new TermFilter(names().createIndexNameTerm(value)); } - @Override public Query fieldQuery(String value, QueryParseContext context) { - return new DeletionAwareConstantScoreQuery(context.cacheFilter(fieldFilter(value), null)); + @Override public Query fieldQuery(String value, @Nullable QueryParseContext context) { + return new DeletionAwareConstantScoreQuery(context.cacheFilter(fieldFilter(value, context), null)); } @Override public boolean useFieldQueryWithQueryString() { diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/TermFilterParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/TermFilterParser.java index 97460797fe7..87d40726b02 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/TermFilterParser.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/TermFilterParser.java @@ -85,7 +85,7 @@ public class TermFilterParser implements FilterParser { MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (smartNameFieldMappers != null) { if (smartNameFieldMappers.hasMapper()) { - filter = smartNameFieldMappers.mapper().fieldFilter(value); + filter = smartNameFieldMappers.mapper().fieldFilter(value, parseContext); } } if (filter == null) { diff --git a/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/simple/SimpleSearchTests.java b/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/simple/SimpleSearchTests.java index b0a11e6b192..0321d15f8c2 100644 --- a/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/simple/SimpleSearchTests.java +++ b/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/simple/SimpleSearchTests.java @@ -72,6 +72,19 @@ public class SimpleSearchTests extends AbstractNodesTests { assertThat(search.hits().totalHits(), equalTo(1l)); } + @Test public void simpleIdTests() { + client.admin().indices().prepareDelete().execute().actionGet(); + client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 1)).execute().actionGet(); + + client.prepareIndex("test", "type", "1").setSource("field", "value").setRefresh(true).execute().actionGet(); + // id is not indexed, but lets see that we automatically convert to + SearchResponse searchResponse = client.prepareSearch().setQuery(QueryBuilders.termQuery("_id", "1")).execute().actionGet(); + assertThat(searchResponse.hits().totalHits(), equalTo(1l)); + + searchResponse = client.prepareSearch().setQuery(QueryBuilders.queryString("_id:1")).execute().actionGet(); + assertThat(searchResponse.hits().totalHits(), equalTo(1l)); + } + @Test public void simpleDateRangeWithUpperInclusiveEnabledTests() throws Exception { client.admin().indices().prepareDelete().execute().actionGet(); client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder()).execute().actionGet();