diff --git a/buildSrc/src/main/resources/checkstyle_suppressions.xml b/buildSrc/src/main/resources/checkstyle_suppressions.xml
index 83b4e332cbf..ab6dc1625d4 100644
--- a/buildSrc/src/main/resources/checkstyle_suppressions.xml
+++ b/buildSrc/src/main/resources/checkstyle_suppressions.xml
@@ -40,7 +40,6 @@
-
diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsResponse.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsResponse.java
index 140a0141a2d..c9b53fee150 100644
--- a/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsResponse.java
+++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsResponse.java
@@ -19,24 +19,37 @@
package org.elasticsearch.action.admin.cluster.shards;
+import org.elasticsearch.Version;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.search.internal.AliasFilter;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
public class ClusterSearchShardsResponse extends ActionResponse implements ToXContent {
+ public static final Version V_5_1_0_UNRELEASED = Version.fromId(5010099);
private ClusterSearchShardsGroup[] groups;
private DiscoveryNode[] nodes;
+ private Map indicesAndFilters;
ClusterSearchShardsResponse() {
}
+ ClusterSearchShardsResponse(ClusterSearchShardsGroup[] groups, DiscoveryNode[] nodes,
+ Map indicesAndFilters) {
+ this.groups = groups;
+ this.nodes = nodes;
+ this.indicesAndFilters = indicesAndFilters;
+ }
+
public ClusterSearchShardsGroup[] getGroups() {
return groups;
}
@@ -45,9 +58,8 @@ public class ClusterSearchShardsResponse extends ActionResponse implements ToXCo
return nodes;
}
- public ClusterSearchShardsResponse(ClusterSearchShardsGroup[] groups, DiscoveryNode[] nodes) {
- this.groups = groups;
- this.nodes = nodes;
+ public Map getIndicesAndFilters() {
+ return indicesAndFilters;
}
@Override
@@ -61,7 +73,15 @@ public class ClusterSearchShardsResponse extends ActionResponse implements ToXCo
for (int i = 0; i < nodes.length; i++) {
nodes[i] = new DiscoveryNode(in);
}
-
+ if (in.getVersion().onOrAfter(V_5_1_0_UNRELEASED)) {
+ int size = in.readVInt();
+ indicesAndFilters = new HashMap<>();
+ for (int i = 0; i < size; i++) {
+ String index = in.readString();
+ AliasFilter aliasFilter = new AliasFilter(in);
+ indicesAndFilters.put(index, aliasFilter);
+ }
+ }
}
@Override
@@ -75,6 +95,13 @@ public class ClusterSearchShardsResponse extends ActionResponse implements ToXCo
for (DiscoveryNode node : nodes) {
node.writeTo(out);
}
+ if (out.getVersion().onOrAfter(V_5_1_0_UNRELEASED)) {
+ out.writeVInt(indicesAndFilters.size());
+ for (Map.Entry entry : indicesAndFilters.entrySet()) {
+ out.writeString(entry.getKey());
+ entry.getValue().writeTo(out);
+ }
+ }
}
@Override
@@ -84,6 +111,20 @@ public class ClusterSearchShardsResponse extends ActionResponse implements ToXCo
node.toXContent(builder, params);
}
builder.endObject();
+ if (indicesAndFilters != null) {
+ builder.startObject("indices");
+ for (Map.Entry entry : indicesAndFilters.entrySet()) {
+ String index = entry.getKey();
+ builder.startObject(index);
+ AliasFilter aliasFilter = entry.getValue();
+ if (aliasFilter.getQueryBuilder() != null) {
+ builder.field("filter");
+ aliasFilter.getQueryBuilder().toXContent(builder, params);
+ }
+ builder.endObject();
+ }
+ builder.endObject();
+ }
builder.startArray("shards");
for (ClusterSearchShardsGroup group : groups) {
group.toXContent(builder, params);
diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java
index 087597d47fc..01aafc0b0a9 100644
--- a/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java
+++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java
@@ -33,21 +33,29 @@ import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.index.Index;
import org.elasticsearch.index.shard.ShardId;
+import org.elasticsearch.indices.IndicesService;
+import org.elasticsearch.search.internal.AliasFilter;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-public class TransportClusterSearchShardsAction extends TransportMasterNodeReadAction {
+public class TransportClusterSearchShardsAction extends
+ TransportMasterNodeReadAction {
+
+ private final IndicesService indicesService;
@Inject
public TransportClusterSearchShardsAction(Settings settings, TransportService transportService, ClusterService clusterService,
- ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
- super(settings, ClusterSearchShardsAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver, ClusterSearchShardsRequest::new);
+ IndicesService indicesService, ThreadPool threadPool, ActionFilters actionFilters,
+ IndexNameExpressionResolver indexNameExpressionResolver) {
+ super(settings, ClusterSearchShardsAction.NAME, transportService, clusterService, threadPool, actionFilters,
+ indexNameExpressionResolver, ClusterSearchShardsRequest::new);
+ this.indicesService = indicesService;
}
@Override
@@ -58,7 +66,8 @@ public class TransportClusterSearchShardsAction extends TransportMasterNodeReadA
@Override
protected ClusterBlockException checkBlock(ClusterSearchShardsRequest request, ClusterState state) {
- return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_READ, indexNameExpressionResolver.concreteIndexNames(state, request));
+ return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_READ,
+ indexNameExpressionResolver.concreteIndexNames(state, request));
}
@Override
@@ -67,12 +76,20 @@ public class TransportClusterSearchShardsAction extends TransportMasterNodeReadA
}
@Override
- protected void masterOperation(final ClusterSearchShardsRequest request, final ClusterState state, final ActionListener listener) {
+ protected void masterOperation(final ClusterSearchShardsRequest request, final ClusterState state,
+ final ActionListener listener) {
ClusterState clusterState = clusterService.state();
String[] concreteIndices = indexNameExpressionResolver.concreteIndexNames(clusterState, request);
Map> routingMap = indexNameExpressionResolver.resolveSearchRouting(state, request.routing(), request.indices());
+ Map indicesAndFilters = new HashMap<>();
+ for (String index : concreteIndices) {
+ AliasFilter aliasFilter = indicesService.buildAliasFilter(clusterState, index, request.indices());
+ indicesAndFilters.put(index, aliasFilter);
+ }
+
Set nodeIds = new HashSet<>();
- GroupShardsIterator groupShardsIterator = clusterService.operationRouting().searchShards(clusterState, concreteIndices, routingMap, request.preference());
+ GroupShardsIterator groupShardsIterator = clusterService.operationRouting().searchShards(clusterState, concreteIndices,
+ routingMap, request.preference());
ShardRouting shard;
ClusterSearchShardsGroup[] groupResponses = new ClusterSearchShardsGroup[groupShardsIterator.size()];
int currentGroup = 0;
@@ -92,6 +109,6 @@ public class TransportClusterSearchShardsAction extends TransportMasterNodeReadA
for (String nodeId : nodeIds) {
nodes[currentNode++] = clusterState.getNodes().get(nodeId);
}
- listener.onResponse(new ClusterSearchShardsResponse(groupResponses, nodes));
+ listener.onResponse(new ClusterSearchShardsResponse(groupResponses, nodes, indicesAndFilters));
}
}
diff --git a/core/src/test/java/org/elasticsearch/VersionTests.java b/core/src/test/java/org/elasticsearch/VersionTests.java
index 6ffa9f0a390..ece8fc7d5af 100644
--- a/core/src/test/java/org/elasticsearch/VersionTests.java
+++ b/core/src/test/java/org/elasticsearch/VersionTests.java
@@ -20,6 +20,7 @@
package org.elasticsearch;
import org.elasticsearch.action.admin.cluster.shards.ClusterSearchShardsRequest;
+import org.elasticsearch.action.admin.cluster.shards.ClusterSearchShardsResponse;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.Settings;
@@ -291,6 +292,7 @@ public class VersionTests extends ESTestCase {
assertUnknownVersion(Script.V_5_1_0_UNRELEASED);
// once we released 5.0.0 and it's added to Version.java we need to remove this constant
assertUnknownVersion(ClusterSearchShardsRequest.V_5_1_0_UNRELEASED);
+ assertUnknownVersion(ClusterSearchShardsResponse.V_5_1_0_UNRELEASED);
}
public static void assertUnknownVersion(Version version) {
diff --git a/core/src/test/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsRequestTests.java b/core/src/test/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsRequestTests.java
index 7c38a7ff656..f5fa046f4c2 100644
--- a/core/src/test/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsRequestTests.java
+++ b/core/src/test/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsRequestTests.java
@@ -54,7 +54,7 @@ public class ClusterSearchShardsRequestTests extends ESTestCase {
request.routing(routings);
}
- Version version = VersionUtils.randomVersion(random());
+ Version version = VersionUtils.randomVersionBetween(random(), Version.V_5_0_0, Version.CURRENT);
try (BytesStreamOutput out = new BytesStreamOutput()) {
out.setVersion(version);
request.writeTo(out);
diff --git a/core/src/test/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsResponseTests.java b/core/src/test/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsResponseTests.java
new file mode 100644
index 00000000000..d2378eaf9c5
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/action/admin/cluster/shards/ClusterSearchShardsResponseTests.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.action.admin.cluster.shards;
+
+import org.elasticsearch.Version;
+import org.elasticsearch.cluster.node.DiscoveryNode;
+import org.elasticsearch.cluster.routing.ShardRouting;
+import org.elasticsearch.cluster.routing.ShardRoutingState;
+import org.elasticsearch.cluster.routing.TestShardRouting;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.io.stream.BytesStreamOutput;
+import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.TransportAddress;
+import org.elasticsearch.index.query.RandomQueryBuilder;
+import org.elasticsearch.index.shard.ShardId;
+import org.elasticsearch.search.SearchModule;
+import org.elasticsearch.search.internal.AliasFilter;
+import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.test.VersionUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ClusterSearchShardsResponseTests extends ESTestCase {
+
+ public void testSerialization() throws Exception {
+ Map indicesAndFilters = new HashMap<>();
+ Set nodes = new HashSet<>();
+ int numShards = randomIntBetween(1, 10);
+ ClusterSearchShardsGroup[] clusterSearchShardsGroups = new ClusterSearchShardsGroup[numShards];
+ for (int i = 0; i < numShards; i++) {
+ String index = randomAsciiOfLengthBetween(3, 10);
+ ShardId shardId = new ShardId(index, randomAsciiOfLength(12), i);
+ String nodeId = randomAsciiOfLength(10);
+ ShardRouting shardRouting = TestShardRouting.newShardRouting(shardId, nodeId, randomBoolean(), ShardRoutingState.STARTED);
+ clusterSearchShardsGroups[i] = new ClusterSearchShardsGroup(shardId, new ShardRouting[]{shardRouting});
+ DiscoveryNode node = new DiscoveryNode(shardRouting.currentNodeId(),
+ new TransportAddress(TransportAddress.META_ADDRESS, randomInt(0xFFFF)), VersionUtils.randomVersion(random()));
+ nodes.add(node);
+ AliasFilter aliasFilter;
+ if (randomBoolean()) {
+ aliasFilter = new AliasFilter(RandomQueryBuilder.createQuery(random()), "alias-" + index);
+ } else {
+ aliasFilter = new AliasFilter(null, Strings.EMPTY_ARRAY);
+ }
+ indicesAndFilters.put(index, aliasFilter);
+ }
+ ClusterSearchShardsResponse clusterSearchShardsResponse = new ClusterSearchShardsResponse(clusterSearchShardsGroups,
+ nodes.toArray(new DiscoveryNode[nodes.size()]), indicesAndFilters);
+
+ SearchModule searchModule = new SearchModule(Settings.EMPTY, false, Collections.emptyList());
+ List entries = new ArrayList<>();
+ entries.addAll(searchModule.getNamedWriteables());
+ NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry(entries);
+ Version version = VersionUtils.randomVersionBetween(random(), Version.V_5_0_0, Version.CURRENT);
+ try(BytesStreamOutput out = new BytesStreamOutput()) {
+ out.setVersion(version);
+ clusterSearchShardsResponse.writeTo(out);
+ try(StreamInput in = new NamedWriteableAwareStreamInput(out.bytes().streamInput(), namedWriteableRegistry)) {
+ in.setVersion(version);
+ ClusterSearchShardsResponse deserialized = new ClusterSearchShardsResponse();
+ deserialized.readFrom(in);
+ assertArrayEquals(clusterSearchShardsResponse.getNodes(), deserialized.getNodes());
+ assertEquals(clusterSearchShardsResponse.getGroups().length, deserialized.getGroups().length);
+ for (int i = 0; i < clusterSearchShardsResponse.getGroups().length; i++) {
+ ClusterSearchShardsGroup clusterSearchShardsGroup = clusterSearchShardsResponse.getGroups()[i];
+ ClusterSearchShardsGroup deserializedGroup = deserialized.getGroups()[i];
+ assertEquals(clusterSearchShardsGroup.getShardId(), deserializedGroup.getShardId());
+ assertEquals(clusterSearchShardsGroup.getIndex(), deserializedGroup.getIndex());
+ assertArrayEquals(clusterSearchShardsGroup.getShards(), deserializedGroup.getShards());
+ }
+ if (version.onOrAfter(ClusterSearchShardsResponse.V_5_1_0_UNRELEASED)) {
+ assertEquals(clusterSearchShardsResponse.getIndicesAndFilters(), deserialized.getIndicesAndFilters());
+ } else {
+ assertNull(deserialized.getIndicesAndFilters());
+ }
+ }
+ }
+ }
+}
diff --git a/docs/reference/search/search-shards.asciidoc b/docs/reference/search/search-shards.asciidoc
index 917a50ae9a7..1515a182d42 100644
--- a/docs/reference/search/search-shards.asciidoc
+++ b/docs/reference/search/search-shards.asciidoc
@@ -3,7 +3,8 @@
The search shards api returns the indices and shards that a search request would
be executed against. This can give useful feedback for working out issues or
-planning optimizations with routing and shard preferences.
+planning optimizations with routing and shard preferences. When filtered aliases
+are used, the filter is returned as part of the `indices` section.
The `index` may be a single value, or comma-separated.
@@ -25,6 +26,9 @@ This will yield the following result:
--------------------------------------------------
{
"nodes": ...,
+ "indices" : {
+ "twitter": { }
+ },
"shards": [
[
{
@@ -107,6 +111,9 @@ This will yield the following result:
--------------------------------------------------
{
"nodes": ...,
+ "indices" : {
+ "twitter": { }
+ },
"shards": [
[
{
diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/search_shards/10_basic.yaml b/rest-api-spec/src/main/resources/rest-api-spec/test/search_shards/10_basic.yaml
index 4bfe6e953b2..4f7d91f42af 100644
--- a/rest-api-spec/src/main/resources/rest-api-spec/test/search_shards/10_basic.yaml
+++ b/rest-api-spec/src/main/resources/rest-api-spec/test/search_shards/10_basic.yaml
@@ -10,3 +10,47 @@
routing: foo
- match: { shards.0.0.index: test_1 }
+
+---
+"Search shards aliases with and without filters":
+ - skip:
+ version: " - 5.0.99"
+ reason: indices section was added in 5.1.0
+
+ - do:
+ indices.create:
+ index: test_index
+ body:
+ settings:
+ index:
+ number_of_shards: 1
+ number_of_replicas: 0
+ mappings:
+ type_1:
+ properties:
+ field:
+ type: text
+ aliases:
+ test_alias_1: {}
+ test_alias_2:
+ filter:
+ term:
+ field : value
+
+ - do:
+ search_shards:
+ index: test_alias_1
+
+ - length: { shards: 1 }
+ - match: { shards.0.0.index: test_index }
+ - is_true: indices.test_index
+ - is_false: indices.test_index.filter
+
+ - do:
+ search_shards:
+ index: test_alias_2
+
+ - length: { shards: 1 }
+ - match: { shards.0.0.index: test_index }
+ - match: { indices.test_index: {filter: { term : { field: { value: value, boost: 1.0}}}}}
+