|
@@ -66,6 +66,7 @@ import org.elasticsearch.script.MockScriptEngine;
|
|
|
import org.elasticsearch.script.MockScriptPlugin;
|
|
|
import org.elasticsearch.script.Script;
|
|
|
import org.elasticsearch.script.ScriptType;
|
|
|
+import org.elasticsearch.search.aggregations.AggregationBuilders;
|
|
|
import org.elasticsearch.search.aggregations.InternalAggregation;
|
|
|
import org.elasticsearch.search.aggregations.MultiBucketConsumerService;
|
|
|
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
|
|
@@ -77,6 +78,7 @@ import org.elasticsearch.search.fetch.ShardFetchRequest;
|
|
|
import org.elasticsearch.search.internal.AliasFilter;
|
|
|
import org.elasticsearch.search.internal.SearchContext;
|
|
|
import org.elasticsearch.search.internal.ShardSearchRequest;
|
|
|
+import org.elasticsearch.search.query.QuerySearchResult;
|
|
|
import org.elasticsearch.search.suggest.SuggestBuilder;
|
|
|
import org.elasticsearch.test.ESSingleNodeTestCase;
|
|
|
import org.junit.Before;
|
|
@@ -168,10 +170,12 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
indexModule.addSearchOperationListener(new SearchOperationListener() {
|
|
|
@Override
|
|
|
public void onNewContext(SearchContext context) {
|
|
|
- if ("throttled_threadpool_index".equals(context.indexShard().shardId().getIndex().getName())) {
|
|
|
- assertThat(Thread.currentThread().getName(), startsWith("elasticsearch[node_s_0][search_throttled]"));
|
|
|
- } else {
|
|
|
- assertThat(Thread.currentThread().getName(), startsWith("elasticsearch[node_s_0][search]"));
|
|
|
+ if (context.query() != null) {
|
|
|
+ if ("throttled_threadpool_index".equals(context.indexShard().shardId().getIndex().getName())) {
|
|
|
+ assertThat(Thread.currentThread().getName(), startsWith("elasticsearch[node_s_0][search_throttled]"));
|
|
|
+ } else {
|
|
|
+ assertThat(Thread.currentThread().getName(), startsWith("elasticsearch[node_s_0][search]"));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -357,15 +361,11 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
final IndexService indexService = indicesService.indexServiceSafe(resolveIndex("index"));
|
|
|
final IndexShard indexShard = indexService.getShard(0);
|
|
|
SearchRequest searchRequest = new SearchRequest().allowPartialSearchResults(true);
|
|
|
- final SearchContext contextWithDefaultTimeout = service.createContext(
|
|
|
- new ShardSearchRequest(
|
|
|
- OriginalIndices.NONE,
|
|
|
- searchRequest,
|
|
|
- indexShard.shardId(),
|
|
|
- 1,
|
|
|
- new AliasFilter(null, Strings.EMPTY_ARRAY),
|
|
|
- 1.0f, -1, null, null)
|
|
|
- );
|
|
|
+ SearchService.SearchRewriteContext rewriteContext = service.acquireSearcherAndRewrite(
|
|
|
+ new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
+ new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null),
|
|
|
+ indexShard);
|
|
|
+ final SearchContext contextWithDefaultTimeout = service.createContext(rewriteContext);
|
|
|
try {
|
|
|
// the search context should inherit the default timeout
|
|
|
assertThat(contextWithDefaultTimeout.timeout(), equalTo(TimeValue.timeValueSeconds(5)));
|
|
@@ -376,15 +376,11 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
|
|
|
final long seconds = randomIntBetween(6, 10);
|
|
|
searchRequest.source(new SearchSourceBuilder().timeout(TimeValue.timeValueSeconds(seconds)));
|
|
|
- final SearchContext context = service.createContext(
|
|
|
- new ShardSearchRequest(
|
|
|
- OriginalIndices.NONE,
|
|
|
- searchRequest,
|
|
|
- indexShard.shardId(),
|
|
|
- 1,
|
|
|
- new AliasFilter(null, Strings.EMPTY_ARRAY),
|
|
|
- 1.0f, -1, null, null)
|
|
|
- );
|
|
|
+ rewriteContext = service.acquireSearcherAndRewrite(
|
|
|
+ new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
+ new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null),
|
|
|
+ indexShard);
|
|
|
+ final SearchContext context = service.createContext(rewriteContext);
|
|
|
try {
|
|
|
// the search context should inherit the query timeout
|
|
|
assertThat(context.timeout(), equalTo(TimeValue.timeValueSeconds(seconds)));
|
|
@@ -412,19 +408,25 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
for (int i = 0; i < indexService.getIndexSettings().getMaxDocvalueFields(); i++) {
|
|
|
searchSourceBuilder.docValueField("field" + i);
|
|
|
}
|
|
|
- try (SearchContext context = service.createContext(
|
|
|
- new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
- new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null))
|
|
|
- ) {
|
|
|
- assertNotNull(context);
|
|
|
+
|
|
|
+ ShardSearchRequest shardRequest = new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
+ new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null);
|
|
|
+
|
|
|
+ {
|
|
|
+ SearchService.SearchRewriteContext rewriteContext = service.acquireSearcherAndRewrite(shardRequest, indexShard);
|
|
|
+ try (SearchContext context = service.createContext(rewriteContext)) {
|
|
|
+ assertNotNull(context);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ SearchService.SearchRewriteContext rewriteContext = service.acquireSearcherAndRewrite(shardRequest, indexShard);
|
|
|
searchSourceBuilder.docValueField("one_field_too_much");
|
|
|
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
|
|
- () -> service.createContext(new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
- new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null)));
|
|
|
+ () -> service.createContext(rewriteContext));
|
|
|
assertEquals(
|
|
|
- "Trying to retrieve too many docvalue_fields. Must be less than or equal to: [100] but was [101]. "
|
|
|
- + "This limit can be set by changing the [index.max_docvalue_fields_search] index level setting.",
|
|
|
- ex.getMessage());
|
|
|
+ "Trying to retrieve too many docvalue_fields. Must be less than or equal to: [100] but was [101]. "
|
|
|
+ + "This limit can be set by changing the [index.max_docvalue_fields_search] index level setting.", ex.getMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -447,20 +449,28 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
searchSourceBuilder.scriptField("field" + i,
|
|
|
new Script(ScriptType.INLINE, MockScriptEngine.NAME, CustomScriptPlugin.DUMMY_SCRIPT, Collections.emptyMap()));
|
|
|
}
|
|
|
- try (SearchContext context = service.createContext(new ShardSearchRequest(OriginalIndices.NONE, searchRequest,
|
|
|
- indexShard.shardId(), 1, new AliasFilter(null, Strings.EMPTY_ARRAY),
|
|
|
- 1.0f, -1, null, null))) {
|
|
|
- assertNotNull(context);
|
|
|
+
|
|
|
+ ShardSearchRequest shardRequest = new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
+ new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null);
|
|
|
+
|
|
|
+ {
|
|
|
+ SearchService.SearchRewriteContext rewriteContext = service.acquireSearcherAndRewrite(shardRequest, indexShard);
|
|
|
+ try (SearchContext context = service.createContext(rewriteContext)) {
|
|
|
+ assertNotNull(context);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
searchSourceBuilder.scriptField("anotherScriptField",
|
|
|
- new Script(ScriptType.INLINE, MockScriptEngine.NAME, CustomScriptPlugin.DUMMY_SCRIPT, Collections.emptyMap()));
|
|
|
+ new Script(ScriptType.INLINE, MockScriptEngine.NAME, CustomScriptPlugin.DUMMY_SCRIPT, Collections.emptyMap()));
|
|
|
+ SearchService.SearchRewriteContext rewriteContext = service.acquireSearcherAndRewrite(shardRequest, indexShard);
|
|
|
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
|
|
- () -> service.createContext(new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
- new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null)));
|
|
|
+ () -> service.createContext(rewriteContext));
|
|
|
assertEquals(
|
|
|
- "Trying to retrieve too many script_fields. Must be less than or equal to: [" + maxScriptFields + "] but was ["
|
|
|
- + (maxScriptFields + 1)
|
|
|
- + "]. This limit can be set by changing the [index.max_script_fields] index level setting.",
|
|
|
- ex.getMessage());
|
|
|
+ "Trying to retrieve too many script_fields. Must be less than or equal to: [" + maxScriptFields + "] but was ["
|
|
|
+ + (maxScriptFields + 1)
|
|
|
+ + "]. This limit can be set by changing the [index.max_script_fields] index level setting.",
|
|
|
+ ex.getMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -477,17 +487,19 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
searchSourceBuilder.scriptField("field" + 0,
|
|
|
new Script(ScriptType.INLINE, MockScriptEngine.NAME, CustomScriptPlugin.DUMMY_SCRIPT, Collections.emptyMap()));
|
|
|
searchSourceBuilder.size(0);
|
|
|
- try (SearchContext context = service.createContext(new ShardSearchRequest(OriginalIndices.NONE,
|
|
|
- searchRequest, indexShard.shardId(), 1, new AliasFilter(null, Strings.EMPTY_ARRAY),
|
|
|
- 1.0f, -1, null, null))) {
|
|
|
- assertEquals(0, context.scriptFields().fields().size());
|
|
|
+ SearchService.SearchRewriteContext rewriteContext = service.acquireSearcherAndRewrite(
|
|
|
+ new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
+ new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null),
|
|
|
+ indexShard);
|
|
|
+ try (SearchContext context = service.createContext(rewriteContext)) {
|
|
|
+ assertEquals(0, context.scriptFields().fields().size());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* test that creating more than the allowed number of scroll contexts throws an exception
|
|
|
*/
|
|
|
- public void testMaxOpenScrollContexts() throws RuntimeException {
|
|
|
+ public void testMaxOpenScrollContexts() throws RuntimeException, IOException {
|
|
|
createIndex("index");
|
|
|
client().prepareIndex("index").setId("1").setSource("field", "value").setRefreshPolicy(IMMEDIATE).get();
|
|
|
|
|
@@ -513,8 +525,10 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
client().prepareSearch("index").setSize(1).setScroll("1m").get();
|
|
|
}
|
|
|
|
|
|
+ SearchService.SearchRewriteContext rewriteContext =
|
|
|
+ service.acquireSearcherAndRewrite(new ShardScrollRequestTest(indexShard.shardId()), indexShard);
|
|
|
ElasticsearchException ex = expectThrows(ElasticsearchException.class,
|
|
|
- () -> service.createAndPutContext(new ShardScrollRequestTest(indexShard.shardId())));
|
|
|
+ () -> service.createAndPutContext(rewriteContext));
|
|
|
assertEquals(
|
|
|
"Trying to create too many scroll contexts. Must be less than or equal to: [" +
|
|
|
SearchService.MAX_OPEN_SCROLL_CONTEXT.get(Settings.EMPTY) + "]. " +
|
|
@@ -592,7 +606,7 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void testCanMatch() throws IOException {
|
|
|
+ public void testCanMatch() throws IOException, InterruptedException {
|
|
|
createIndex("index");
|
|
|
final SearchService service = getInstanceFromNode(SearchService.class);
|
|
|
final IndicesService indicesService = getInstanceFromNode(IndicesService.class);
|
|
@@ -625,11 +639,32 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
new AliasFilter(null, Strings.EMPTY_ARRAY), 1f, -1, null, null)).canMatch());
|
|
|
assertEquals(numWrapReader, numWrapInvocations.get());
|
|
|
|
|
|
- // make sure that the wrapper is called when the context is actually created
|
|
|
- service.createContext(new ShardSearchRequest(OriginalIndices.NONE, searchRequest,
|
|
|
- indexShard.shardId(), 1, new AliasFilter(null, Strings.EMPTY_ARRAY),
|
|
|
- 1f, -1, null, null)).close();
|
|
|
- assertEquals(numWrapReader+1, numWrapInvocations.get());
|
|
|
+ ShardSearchRequest request = new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(), 1,
|
|
|
+ new AliasFilter(null, Strings.EMPTY_ARRAY), 1.0f, -1, null, null);
|
|
|
+
|
|
|
+ CountDownLatch latch = new CountDownLatch(1);
|
|
|
+ SearchShardTask task = new SearchShardTask(123L, "", "", "", null, Collections.emptyMap());
|
|
|
+ service.executeQueryPhase(request, task, new ActionListener<SearchPhaseResult>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(SearchPhaseResult searchPhaseResult) {
|
|
|
+ try {
|
|
|
+ // make sure that the wrapper is called when the query is actually executed
|
|
|
+ assertEquals(numWrapReader+1, numWrapInvocations.get());
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(Exception e) {
|
|
|
+ try {
|
|
|
+ throw new AssertionError(e);
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ latch.await();
|
|
|
}
|
|
|
|
|
|
public void testCanRewriteToMatchNone() {
|
|
@@ -744,18 +779,123 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
|
|
final IndexService indexService = createIndex(index);
|
|
|
final SearchService service = getInstanceFromNode(SearchService.class);
|
|
|
final ShardId shardId = new ShardId(indexService.index(), 0);
|
|
|
+ IndexShard indexShard = indexService.getShard(0);
|
|
|
|
|
|
- NullPointerException e = expectThrows(NullPointerException.class,
|
|
|
- () -> service.createContext(
|
|
|
- new ShardSearchRequest(shardId, 0, null) {
|
|
|
- @Override
|
|
|
- public SearchType searchType() {
|
|
|
- // induce an artificial NPE
|
|
|
- throw new NullPointerException("expected");
|
|
|
- }
|
|
|
+ SearchService.SearchRewriteContext rewriteContext = service.acquireSearcherAndRewrite(
|
|
|
+ new ShardSearchRequest(shardId, 0, AliasFilter.EMPTY) {
|
|
|
+ @Override
|
|
|
+ public SearchType searchType() {
|
|
|
+ // induce an artificial NPE
|
|
|
+ throw new NullPointerException("expected");
|
|
|
}
|
|
|
- ));
|
|
|
+ }, indexShard);
|
|
|
+ NullPointerException e = expectThrows(NullPointerException.class,
|
|
|
+ () -> service.createContext(rewriteContext));
|
|
|
assertEquals("expected", e.getMessage());
|
|
|
assertEquals("should have 2 store refs (IndexService + InternalEngine)", 2, indexService.getShard(0).store().refCount());
|
|
|
}
|
|
|
+
|
|
|
+ public void testMatchNoDocsEmptyResponse() throws InterruptedException {
|
|
|
+ createIndex("index");
|
|
|
+ Thread currentThread = Thread.currentThread();
|
|
|
+ SearchService service = getInstanceFromNode(SearchService.class);
|
|
|
+ IndicesService indicesService = getInstanceFromNode(IndicesService.class);
|
|
|
+ IndexService indexService = indicesService.indexServiceSafe(resolveIndex("index"));
|
|
|
+ IndexShard indexShard = indexService.getShard(0);
|
|
|
+ SearchRequest searchRequest = new SearchRequest()
|
|
|
+ .allowPartialSearchResults(false)
|
|
|
+ .source(new SearchSourceBuilder()
|
|
|
+ .aggregation(AggregationBuilders.count("count").field("value")));
|
|
|
+ ShardSearchRequest shardRequest = new ShardSearchRequest(OriginalIndices.NONE, searchRequest, indexShard.shardId(),
|
|
|
+ 5, AliasFilter.EMPTY, 1.0f, 0, null, null);
|
|
|
+ SearchShardTask task = new SearchShardTask(123L, "", "", "", null, Collections.emptyMap());
|
|
|
+
|
|
|
+ {
|
|
|
+ CountDownLatch latch = new CountDownLatch(1);
|
|
|
+ shardRequest.source().query(new MatchAllQueryBuilder());
|
|
|
+ service.executeQueryPhase(shardRequest, task, new ActionListener<>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(SearchPhaseResult result) {
|
|
|
+ try {
|
|
|
+ assertNotSame(Thread.currentThread(), currentThread);
|
|
|
+ assertThat(Thread.currentThread().getName(), startsWith("elasticsearch[node_s_0][search]"));
|
|
|
+ assertThat(result, instanceOf(QuerySearchResult.class));
|
|
|
+ assertFalse(result.queryResult().isNull());
|
|
|
+ assertNotNull(result.queryResult().topDocs());
|
|
|
+ assertNotNull(result.queryResult().aggregations());
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(Exception exc) {
|
|
|
+ try {
|
|
|
+ throw new AssertionError(exc);
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ latch.await();
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ CountDownLatch latch = new CountDownLatch(1);
|
|
|
+ shardRequest.source().query(new MatchNoneQueryBuilder());
|
|
|
+ service.executeQueryPhase(shardRequest, task, new ActionListener<>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(SearchPhaseResult result) {
|
|
|
+ try {
|
|
|
+ assertNotSame(Thread.currentThread(), currentThread);
|
|
|
+ assertThat(Thread.currentThread().getName(), startsWith("elasticsearch[node_s_0][search]"));
|
|
|
+ assertThat(result, instanceOf(QuerySearchResult.class));
|
|
|
+ assertFalse(result.queryResult().isNull());
|
|
|
+ assertNotNull(result.queryResult().topDocs());
|
|
|
+ assertNotNull(result.queryResult().aggregations());
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(Exception exc) {
|
|
|
+ try {
|
|
|
+ throw new AssertionError(exc);
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ latch.await();
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ CountDownLatch latch = new CountDownLatch(1);
|
|
|
+ shardRequest.canReturnNullResponseIfMatchNoDocs(true);
|
|
|
+ service.executeQueryPhase(shardRequest, task, new ActionListener<>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(SearchPhaseResult result) {
|
|
|
+ try {
|
|
|
+ // make sure we don't use the search threadpool
|
|
|
+ assertSame(Thread.currentThread(), currentThread);
|
|
|
+ assertThat(result, instanceOf(QuerySearchResult.class));
|
|
|
+ assertTrue(result.queryResult().isNull());
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(Exception e) {
|
|
|
+ try {
|
|
|
+ throw new AssertionError(e);
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ latch.await();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|