diff --git a/rest-api-spec/api/search.json b/rest-api-spec/api/search.json index be03ddc700f2b..0ec64a7e0ec29 100644 --- a/rest-api-spec/api/search.json +++ b/rest-api-spec/api/search.json @@ -146,6 +146,10 @@ "version": { "type" : "boolean", "description" : "Specify whether to return document version as part of a hit" + }, + "query_cache": { + "type" : "boolean", + "description" : "Specify if query cache should be used for this request or not, defaults to index level setting" } } }, diff --git a/src/main/java/org/elasticsearch/action/search/MultiSearchRequest.java b/src/main/java/org/elasticsearch/action/search/MultiSearchRequest.java index 6209af695ce3c..7f970f21d8032 100644 --- a/src/main/java/org/elasticsearch/action/search/MultiSearchRequest.java +++ b/src/main/java/org/elasticsearch/action/search/MultiSearchRequest.java @@ -137,6 +137,8 @@ public MultiSearchRequest add(BytesReference data, boolean contentUnsafe, @Nulla searchRequest.types(Strings.splitStringByCommaToArray(parser.text())); } else if ("search_type".equals(currentFieldName) || "searchType".equals(currentFieldName)) { searchRequest.searchType(parser.text()); + } else if ("query_cache".equals(currentFieldName) || "queryCache".equals(currentFieldName)) { + searchRequest.queryCache(parser.booleanValue()); } else if ("preference".equals(currentFieldName)) { searchRequest.preference(parser.text()); } else if ("routing".equals(currentFieldName)) { diff --git a/src/main/java/org/elasticsearch/action/search/SearchRequest.java b/src/main/java/org/elasticsearch/action/search/SearchRequest.java index 26e998a3f3310..3410786fb85fb 100644 --- a/src/main/java/org/elasticsearch/action/search/SearchRequest.java +++ b/src/main/java/org/elasticsearch/action/search/SearchRequest.java @@ -81,6 +81,7 @@ public class SearchRequest extends ActionRequest implements Indic private BytesReference extraSource; private boolean extraSourceUnsafe; + private Boolean queryCache; private Scroll scroll; @@ -493,6 +494,20 @@ public SearchRequest scroll(String keepAlive) { return scroll(new Scroll(TimeValue.parseTimeValue(keepAlive, null))); } + /** + * Sets if this request should use the query cache or not, assuming that it can (for + * example, if "now" is used, it will never be cached). By default (not set, or null, + * will default to the index level setting if query cache is enabled or not). + */ + public SearchRequest queryCache(Boolean queryCache) { + this.queryCache = queryCache; + return this; + } + + public Boolean queryCache() { + return this.queryCache; + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -533,6 +548,10 @@ public void readFrom(StreamInput in) throws IOException { templateParams = (Map) in.readGenericValue(); } } + + if (in.getVersion().onOrAfter(Version.V_1_4_0)) { + queryCache = in.readOptionalBoolean(); + } } @Override @@ -574,5 +593,9 @@ public void writeTo(StreamOutput out) throws IOException { out.writeGenericValue(templateParams); } } + + if (out.getVersion().onOrAfter(Version.V_1_4_0)) { + out.writeOptionalBoolean(queryCache); + } } } diff --git a/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java b/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java index 84d43c87a4bd0..53bda043482e2 100644 --- a/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java +++ b/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java @@ -1068,6 +1068,16 @@ public SearchRequestBuilder setTemplateSource(BytesReference source) { return this; } + /** + * Sets if this request should use the query cache or not, assuming that it can (for + * example, if "now" is used, it will never be cached). By default (not set, or null, + * will default to the index level setting if query cache is enabled or not). + */ + public SearchRequestBuilder setQueryCache(Boolean queryCache) { + request.queryCache(queryCache); + return this; + } + /** * Sets the source builder to be used with this request. Note, any operations done * on this require builder before are discarded as this internal builder replaces diff --git a/src/main/java/org/elasticsearch/indices/cache/query/IndicesQueryCache.java b/src/main/java/org/elasticsearch/indices/cache/query/IndicesQueryCache.java index 9d8b856e90b64..7d7f94a8374bd 100644 --- a/src/main/java/org/elasticsearch/indices/cache/query/IndicesQueryCache.java +++ b/src/main/java/org/elasticsearch/indices/cache/query/IndicesQueryCache.java @@ -187,7 +187,12 @@ public boolean canCache(ShardSearchRequest request, SearchContext context) { if (index == null) { // in case we didn't yet have the cluster state, or it just got deleted return false; } - if (!index.settings().getAsBoolean(INDEX_CACHE_QUERY_ENABLED, Boolean.FALSE)) { + // if not explicitly set in the request, use the index setting, if not, use the request + if (request.queryCache() == null) { + if (!index.settings().getAsBoolean(INDEX_CACHE_QUERY_ENABLED, Boolean.FALSE)) { + return false; + } + } else if (!request.queryCache()) { return false; } // if the reader is not a directory reader, we can't get the version from it @@ -199,7 +204,6 @@ public boolean canCache(ShardSearchRequest request, SearchContext context) { if (context.nowInMillisUsed()) { return false; } - // TODO allow to have a queryCache level flag on the request as well return true; } diff --git a/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java b/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java index 0ea389b3ef4e2..acf8f0f7559ad 100644 --- a/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java +++ b/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java @@ -109,6 +109,7 @@ public static SearchRequest parseSearchRequest(RestRequest request) { searchRequest.extraSource(parseSearchSource(request)); searchRequest.searchType(request.param("search_type")); + searchRequest.queryCache(request.paramAsBoolean("query_cache", null)); String scroll = request.param("scroll"); if (scroll != null) { diff --git a/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java b/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java index 89d9f63ce44e4..c788ce7c65a5a 100644 --- a/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java +++ b/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java @@ -78,6 +78,7 @@ public class ShardSearchRequest extends TransportRequest implements IndicesReque private String templateName; private ScriptService.ScriptType templateType; private Map templateParams; + private Boolean queryCache; private long nowInMillis; @@ -101,6 +102,7 @@ public ShardSearchRequest(SearchRequest searchRequest, ShardRouting shardRouting this.scroll = searchRequest.scroll(); this.types = searchRequest.types(); this.useSlowScroll = useSlowScroll; + this.queryCache = searchRequest.queryCache(); } public ShardSearchRequest(ShardRouting shardRouting, int numberOfShards, SearchType searchType) { @@ -221,6 +223,10 @@ public boolean useSlowScroll() { return useSlowScroll; } + public Boolean queryCache() { + return this.queryCache; + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -255,6 +261,10 @@ public void readFrom(StreamInput in) throws IOException { // This means that this request was send from a 1.0.x or 1.1.x node and we need to fallback to slow scroll. useSlowScroll = in.getVersion().before(ParsedScrollId.SCROLL_SEARCH_AFTER_MINIMUM_VERSION); } + + if (in.getVersion().onOrAfter(Version.V_1_4_0)) { + queryCache = in.readOptionalBoolean(); + } } @Override @@ -299,5 +309,9 @@ public void writeTo(StreamOutput out, boolean asKey) throws IOException { if (out.getVersion().onOrAfter(ParsedScrollId.SCROLL_SEARCH_AFTER_MINIMUM_VERSION)) { out.writeBoolean(useSlowScroll); } + + if (out.getVersion().onOrAfter(Version.V_1_4_0)) { + out.writeOptionalBoolean(queryCache); + } } } diff --git a/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java b/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java index d574a02071705..282797d1213fa 100644 --- a/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java +++ b/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java @@ -236,6 +236,25 @@ public void run() { client().admin().indices().prepareClearCache().setQueryCache(true).get(); // clean the cache assertThat(client().admin().indices().prepareStats("idx").setQueryCache(true).get().getTotal().getQueryCache().getMemorySizeInBytes(), equalTo(0l)); + + // test explicit request parameter + + assertThat(client().prepareSearch("idx").setSearchType(SearchType.COUNT).setQueryCache(false).get().getHits().getTotalHits(), equalTo((long) numDocs)); + assertThat(client().admin().indices().prepareStats("idx").setQueryCache(true).get().getTotal().getQueryCache().getMemorySizeInBytes(), equalTo(0l)); + + assertThat(client().prepareSearch("idx").setSearchType(SearchType.COUNT).setQueryCache(true).get().getHits().getTotalHits(), equalTo((long) numDocs)); + assertThat(client().admin().indices().prepareStats("idx").setQueryCache(true).get().getTotal().getQueryCache().getMemorySizeInBytes(), greaterThan(0l)); + + // set the index level setting to false, and see that the reverse works + + client().admin().indices().prepareClearCache().setQueryCache(true).get(); // clean the cache + assertAcked(client().admin().indices().prepareUpdateSettings("idx").setSettings(ImmutableSettings.builder().put(IndicesQueryCache.INDEX_CACHE_QUERY_ENABLED, false))); + + assertThat(client().prepareSearch("idx").setSearchType(SearchType.COUNT).get().getHits().getTotalHits(), equalTo((long) numDocs)); + assertThat(client().admin().indices().prepareStats("idx").setQueryCache(true).get().getTotal().getQueryCache().getMemorySizeInBytes(), equalTo(0l)); + + assertThat(client().prepareSearch("idx").setSearchType(SearchType.COUNT).setQueryCache(true).get().getHits().getTotalHits(), equalTo((long) numDocs)); + assertThat(client().admin().indices().prepareStats("idx").setQueryCache(true).get().getTotal().getQueryCache().getMemorySizeInBytes(), greaterThan(0l)); } @Test