Add support for filtering aliases to Search
This commit is contained in:
parent
becf4baaa2
commit
e3bffba327
|
@ -84,8 +84,8 @@ public class TransportSearchAction extends BaseAction<SearchRequest, SearchRespo
|
|||
if (optimizeSingleShard && searchRequest.searchType() != SCAN && searchRequest.searchType() != COUNT) {
|
||||
try {
|
||||
ClusterState clusterState = clusterService.state();
|
||||
searchRequest.indices(clusterState.metaData().concreteIndices(searchRequest.indices()));
|
||||
GroupShardsIterator groupIt = clusterService.operationRouting().searchShards(clusterState, searchRequest.indices(), searchRequest.queryHint(), searchRequest.routing(), searchRequest.preference());
|
||||
String[] concreteIndices = clusterState.metaData().concreteIndices(searchRequest.indices());
|
||||
GroupShardsIterator groupIt = clusterService.operationRouting().searchShards(clusterState, concreteIndices, searchRequest.queryHint(), searchRequest.routing(), searchRequest.preference());
|
||||
if (groupIt.size() == 1) {
|
||||
// if we only have one group, then we always want Q_A_F, no need for DFS, and no need to do THEN since we hit one shard
|
||||
searchRequest.searchType(QUERY_AND_FETCH);
|
||||
|
|
|
@ -67,12 +67,13 @@ public abstract class TransportSearchHelper {
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static InternalSearchRequest internalSearchRequest(ShardRouting shardRouting, int numberOfShards, SearchRequest request) {
|
||||
public static InternalSearchRequest internalSearchRequest(ShardRouting shardRouting, int numberOfShards, SearchRequest request, String[] filteringAliases) {
|
||||
InternalSearchRequest internalRequest = new InternalSearchRequest(shardRouting, numberOfShards, request.searchType());
|
||||
internalRequest.source(request.source(), request.sourceOffset(), request.sourceLength());
|
||||
internalRequest.extraSource(request.extraSource(), request.extraSourceOffset(), request.extraSourceLength());
|
||||
internalRequest.scroll(request.scroll());
|
||||
internalRequest.timeout(request.timeout());
|
||||
internalRequest.filteringAliases(filteringAliases);
|
||||
internalRequest.types(request.types());
|
||||
return internalRequest;
|
||||
}
|
||||
|
|
|
@ -104,13 +104,13 @@ public abstract class TransportSearchTypeAction extends BaseAction<SearchRequest
|
|||
|
||||
nodes = clusterState.nodes();
|
||||
|
||||
request.indices(clusterState.metaData().concreteIndices(request.indices()));
|
||||
String[] concreteIndices = clusterState.metaData().concreteIndices(request.indices());
|
||||
|
||||
for (String index : request.indices()) {
|
||||
for (String index : concreteIndices) {
|
||||
clusterState.blocks().indexBlockedRaiseException(ClusterBlockLevel.READ, index);
|
||||
}
|
||||
|
||||
shardsIts = clusterService.operationRouting().searchShards(clusterState, request.indices(), request.queryHint(), request.routing(), request.preference());
|
||||
shardsIts = clusterService.operationRouting().searchShards(clusterState, concreteIndices, request.queryHint(), request.routing(), request.preference());
|
||||
expectedSuccessfulOps = shardsIts.size();
|
||||
// we need to add 1 for non active partition, since we count it in the total!
|
||||
expectedTotalOps = shardsIts.totalSizeActiveWith1ForEmpty();
|
||||
|
@ -189,7 +189,8 @@ public abstract class TransportSearchTypeAction extends BaseAction<SearchRequest
|
|||
if (node == null) {
|
||||
onFirstPhaseResult(shard, shardIt, null);
|
||||
} else {
|
||||
sendExecuteFirstPhase(node, internalSearchRequest(shard, shardsIts.size(), request), new SearchServiceListener<FirstResult>() {
|
||||
String[] filteringAliases = clusterService.state().metaData().filteringAliases(shard.index(), request.indices());
|
||||
sendExecuteFirstPhase(node, internalSearchRequest(shard, shardsIts.size(), request, filteringAliases), new SearchServiceListener<FirstResult>() {
|
||||
@Override public void onResult(FirstResult result) {
|
||||
onFirstPhaseResult(shard, result, shardIt);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.elasticsearch.indices.IndexMissingException;
|
|||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static org.elasticsearch.common.collect.Lists.newArrayList;
|
||||
import static org.elasticsearch.common.collect.MapBuilder.*;
|
||||
import static org.elasticsearch.common.collect.Sets.*;
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.*;
|
||||
|
@ -54,6 +55,9 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
|
||||
private final ImmutableSet<String> aliases;
|
||||
|
||||
// This map indicates if an alias associated with an index is filtering alias
|
||||
private final ImmutableMap<String, ImmutableMap<String, Boolean>> indexToAliasFilteringRequiredMap;
|
||||
|
||||
private final ImmutableMap<String, String[]> aliasAndIndexToIndexMap;
|
||||
|
||||
private MetaData(ImmutableMap<String, IndexMetaData> indices, ImmutableMap<String, IndexTemplateMetaData> templates) {
|
||||
|
@ -79,6 +83,23 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
}
|
||||
this.aliases = ImmutableSet.copyOf(aliases);
|
||||
|
||||
// build filtering required map
|
||||
MapBuilder<String, ImmutableMap<String, Boolean>> filteringRequiredMap = newMapBuilder();
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
MapBuilder<String, Boolean> indexFilteringRequiredMap = newMapBuilder();
|
||||
// Filtering is not required for the index itself
|
||||
indexFilteringRequiredMap.put(indexMetaData.index(), false);
|
||||
for (AliasMetaData aliasMetaData : indexMetaData.aliases().values()) {
|
||||
if (aliasMetaData.filter() != null) {
|
||||
indexFilteringRequiredMap.put(aliasMetaData.alias(), true);
|
||||
} else {
|
||||
indexFilteringRequiredMap.put(aliasMetaData.alias(), false);
|
||||
}
|
||||
}
|
||||
filteringRequiredMap.put(indexMetaData.index(), indexFilteringRequiredMap.immutableMap());
|
||||
}
|
||||
indexToAliasFilteringRequiredMap = filteringRequiredMap.immutableMap();
|
||||
|
||||
// build aliasAndIndex to Index map
|
||||
MapBuilder<String, Set<String>> tmpAliasAndIndexToIndexBuilder = newMapBuilder();
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
|
@ -252,6 +273,66 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
return totalNumberOfShards();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterates through the list of indices and selects the effective list of filtering aliases for the
|
||||
* given index.
|
||||
*
|
||||
* <p>Only aliases with filters are returned. If the indices list contains a non-filtering reference to
|
||||
* the index itself - null is returned. Returns <tt>null</tt> if no filtering is required.</p>
|
||||
*/
|
||||
public String[] filteringAliases(String index, String... indices) {
|
||||
if (indices == null || indices.length == 0) {
|
||||
return null;
|
||||
}
|
||||
// optimize for the most common single index/alias scenario
|
||||
if (indices.length == 1) {
|
||||
String alias = indices[0];
|
||||
// This list contains "_all" - no filtering needed
|
||||
if (alias.equals("_all")) {
|
||||
return null;
|
||||
}
|
||||
ImmutableMap<String, Boolean> aliasToFilteringRequiredMap = indexToAliasFilteringRequiredMap.get(index);
|
||||
if (aliasToFilteringRequiredMap == null) {
|
||||
// Shouldn't happen
|
||||
throw new IndexMissingException(new Index(index));
|
||||
}
|
||||
Boolean filteringRequired = aliasToFilteringRequiredMap.get(alias);
|
||||
if (filteringRequired == null || !filteringRequired) {
|
||||
return null;
|
||||
}
|
||||
return new String[]{alias};
|
||||
}
|
||||
List<String> filteringAliases = null;
|
||||
for (String alias : indices) {
|
||||
ImmutableMap<String, Boolean> aliasToFilteringRequiredMap = indexToAliasFilteringRequiredMap.get(index);
|
||||
if (aliasToFilteringRequiredMap == null) {
|
||||
// Shouldn't happen
|
||||
throw new IndexMissingException(new Index(index));
|
||||
}
|
||||
Boolean filteringRequired = aliasToFilteringRequiredMap.get(alias);
|
||||
// Check that this is an alias for the current index
|
||||
// Otherwise - skip it
|
||||
if (filteringRequired != null) {
|
||||
if (filteringRequired) {
|
||||
// If filtering required - add it to the list of filters
|
||||
if (filteringAliases == null) {
|
||||
filteringAliases = newArrayList();
|
||||
}
|
||||
filteringAliases.add(alias);
|
||||
} else {
|
||||
// If not, we have a non filtering alias for this index - no filtering needed
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filteringAliases == null) {
|
||||
return null;
|
||||
}
|
||||
return filteringAliases.toArray(new String[filteringAliases.size()]);
|
||||
}
|
||||
|
||||
|
||||
@Override public UnmodifiableIterator<IndexMetaData> iterator() {
|
||||
return indices.values().iterator();
|
||||
}
|
||||
|
|
|
@ -37,11 +37,10 @@ import org.elasticsearch.index.query.IndexQueryParserService;
|
|||
import org.elasticsearch.index.query.xcontent.XContentIndexQueryParser;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
import org.elasticsearch.indices.AliasFilterParsingException;
|
||||
import org.elasticsearch.indices.InvalidAliasNameException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.common.collect.Lists.*;
|
||||
import static org.elasticsearch.common.collect.MapBuilder.*;
|
||||
|
||||
/**
|
||||
|
@ -73,56 +72,42 @@ public class IndexAliasesService extends AbstractIndexComponent implements Itera
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the filter associated with a possibly aliased indices.
|
||||
* Returns the filter associated with listed filtering aliases.
|
||||
*
|
||||
* <p>Returns <tt>null</tt> if no filtering is required. Note, if no alias if found for the provided value
|
||||
* then no filtering is done.</p>
|
||||
* <p>The list of filtering aliases should be obtained by calling MetaData.filteringAliases.
|
||||
* Returns <tt>null</tt> if no filtering is required.</p>
|
||||
*/
|
||||
public Filter aliasFilter(String... indices) {
|
||||
if (indices == null) {
|
||||
public Filter aliasFilter(String... aliases) {
|
||||
if (aliases == null || aliases.length == 0) {
|
||||
return null;
|
||||
}
|
||||
// optimize for the most common single index/alias scenario
|
||||
if (indices.length == 1) {
|
||||
String alias = indices[0];
|
||||
// The list contains the index itself - no filtering needed
|
||||
if (alias.equals(index.name())) {
|
||||
return null;
|
||||
}
|
||||
IndexAlias indexAlias = aliases.get(alias);
|
||||
if (aliases.length == 1) {
|
||||
IndexAlias indexAlias = alias(aliases[0]);
|
||||
if (indexAlias == null) {
|
||||
return null;
|
||||
// This shouldn't happen unless alias disappeared after filteringAliases was called.
|
||||
throw new InvalidAliasNameException(index, aliases[0], "Unknown alias name was passed to alias Filter");
|
||||
}
|
||||
return indexAlias.parsedFilter();
|
||||
}
|
||||
List<Filter> filters = null;
|
||||
for (String alias : indices) {
|
||||
// The list contains the index itself - no filtering needed
|
||||
if (alias.equals(index.name())) {
|
||||
return null;
|
||||
}
|
||||
IndexAlias indexAlias = aliases.get(alias);
|
||||
if (indexAlias != null) {
|
||||
// The list contains a non-filtering alias - no filtering needed
|
||||
if (indexAlias.parsedFilter() == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (filters == null) {
|
||||
filters = newArrayList();
|
||||
}
|
||||
filters.add(indexAlias.parsedFilter());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filters == null) {
|
||||
return null;
|
||||
}
|
||||
if (filters.size() == 1) {
|
||||
return filters.get(0);
|
||||
} else {
|
||||
XBooleanFilter combined = new XBooleanFilter();
|
||||
for (Filter filter : filters) {
|
||||
combined.add(new FilterClause(filter, BooleanClause.Occur.SHOULD));
|
||||
for (String alias : aliases) {
|
||||
IndexAlias indexAlias = alias(alias);
|
||||
if (indexAlias == null) {
|
||||
// This shouldn't happen unless alias disappeared after filteringAliases was called.
|
||||
throw new InvalidAliasNameException(index, aliases[0], "Unknown alias name was passed to alias Filter");
|
||||
}
|
||||
if (indexAlias.parsedFilter() != null) {
|
||||
combined.add(new FilterClause(indexAlias.parsedFilter(), BooleanClause.Occur.SHOULD));
|
||||
} else {
|
||||
// The filter might be null only if filter was removed after filteringAliases was called
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (combined.getShouldFilters().size() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (combined.getShouldFilters().size() == 1) {
|
||||
return combined.getShouldFilters().get(0);
|
||||
}
|
||||
return combined;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.search;
|
||||
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.elasticsearch.ElasticSearchException;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
|
@ -396,6 +397,9 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
|
|||
context.size(10);
|
||||
}
|
||||
|
||||
Filter aliasFilter = indexService.aliasesService().aliasFilter(request.filteringAliases());
|
||||
context.aliasFilter(aliasFilter);
|
||||
|
||||
// pre process
|
||||
dfsPhase.preProcess(context);
|
||||
queryPhase.preProcess(context);
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.elasticsearch.common.collect.Maps;
|
|||
import org.elasticsearch.common.lucene.MinimumScoreCollector;
|
||||
import org.elasticsearch.common.lucene.MultiCollector;
|
||||
import org.elasticsearch.common.lucene.search.FilteredCollector;
|
||||
import org.elasticsearch.common.lucene.search.XBooleanFilter;
|
||||
import org.elasticsearch.index.engine.Engine;
|
||||
import org.elasticsearch.search.dfs.CachedDfSource;
|
||||
|
||||
|
@ -165,16 +166,30 @@ public class ContextIndexSearcher extends ExtendedIndexSearcher {
|
|||
collector = new MinimumScoreCollector(collector, searchContext.minimumScore());
|
||||
}
|
||||
|
||||
Filter combinedFilter;
|
||||
if (filter == null) {
|
||||
combinedFilter = searchContext.aliasFilter();
|
||||
} else {
|
||||
if (searchContext.aliasFilter() != null) {
|
||||
XBooleanFilter booleanFilter = new XBooleanFilter();
|
||||
booleanFilter.add(new FilterClause(filter, BooleanClause.Occur.MUST));
|
||||
booleanFilter.add(new FilterClause(searchContext.aliasFilter(), BooleanClause.Occur.MUST));
|
||||
combinedFilter = booleanFilter;
|
||||
} else {
|
||||
combinedFilter = filter;
|
||||
}
|
||||
}
|
||||
|
||||
// we only compute the doc id set once since within a context, we execute the same query always...
|
||||
if (searchContext.timeout() != null) {
|
||||
searchContext.queryResult().searchTimedOut(false);
|
||||
try {
|
||||
super.search(weight, filter, collector);
|
||||
super.search(weight, combinedFilter, collector);
|
||||
} catch (TimeLimitingCollector.TimeExceededException e) {
|
||||
searchContext.queryResult().searchTimedOut(true);
|
||||
}
|
||||
} else {
|
||||
super.search(weight, filter, collector);
|
||||
super.search(weight, combinedFilter, collector);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,6 +70,8 @@ public class InternalSearchRequest implements Streamable {
|
|||
|
||||
private String[] types = Strings.EMPTY_ARRAY;
|
||||
|
||||
private String[] filteringAliases;
|
||||
|
||||
private byte[] source;
|
||||
private int sourceOffset;
|
||||
private int sourceLength;
|
||||
|
@ -168,6 +170,14 @@ public class InternalSearchRequest implements Streamable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public String[] filteringAliases() {
|
||||
return filteringAliases;
|
||||
}
|
||||
|
||||
public void filteringAliases(String[] filteringAliases) {
|
||||
this.filteringAliases = filteringAliases;
|
||||
}
|
||||
|
||||
public String[] types() {
|
||||
return types;
|
||||
}
|
||||
|
@ -210,6 +220,15 @@ public class InternalSearchRequest implements Streamable {
|
|||
types[i] = in.readUTF();
|
||||
}
|
||||
}
|
||||
int indicesSize = in.readVInt();
|
||||
if (indicesSize > 0) {
|
||||
filteringAliases = new String[indicesSize];
|
||||
for (int i = 0; i < indicesSize; i++) {
|
||||
filteringAliases[i] = in.readUTF();
|
||||
}
|
||||
} else {
|
||||
filteringAliases = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void writeTo(StreamOutput out) throws IOException {
|
||||
|
@ -245,5 +264,13 @@ public class InternalSearchRequest implements Streamable {
|
|||
for (String type : types) {
|
||||
out.writeUTF(type);
|
||||
}
|
||||
if (filteringAliases != null) {
|
||||
out.writeVInt(filteringAliases.length);
|
||||
for (String index : filteringAliases) {
|
||||
out.writeUTF(index);
|
||||
}
|
||||
} else {
|
||||
out.writeVInt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,6 +128,8 @@ public class SearchContext implements Releasable {
|
|||
|
||||
private Filter filter;
|
||||
|
||||
private Filter aliasFilter;
|
||||
|
||||
private int[] docIdsToLoad;
|
||||
|
||||
private int docsIdsToLoadFrom;
|
||||
|
@ -343,6 +345,15 @@ public class SearchContext implements Releasable {
|
|||
return this.filter;
|
||||
}
|
||||
|
||||
public SearchContext aliasFilter(Filter aliasFilter) {
|
||||
this.aliasFilter = aliasFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Filter aliasFilter() {
|
||||
return aliasFilter;
|
||||
}
|
||||
|
||||
public String queryParserName() {
|
||||
return queryParserName;
|
||||
}
|
||||
|
|
|
@ -37,12 +37,13 @@ import org.elasticsearch.index.query.IndexQueryParserService;
|
|||
import org.elasticsearch.index.query.xcontent.XContentFilterBuilder;
|
||||
import org.elasticsearch.index.settings.IndexSettingsModule;
|
||||
import org.elasticsearch.index.similarity.SimilarityModule;
|
||||
import org.elasticsearch.indices.InvalidAliasNameException;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.index.query.xcontent.FilterBuilders.termFilter;
|
||||
import static org.elasticsearch.index.query.xcontent.FilterBuilders.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
|
@ -76,7 +77,7 @@ public class IndexAliasesServiceTests {
|
|||
return new CompressedString(builder.string());
|
||||
}
|
||||
|
||||
@Test public void testAliasFilter() throws Exception {
|
||||
@Test public void testFilteringAliases() throws Exception {
|
||||
IndexAliasesService indexAliasesService = newIndexAliasesService();
|
||||
indexAliasesService.add("cats", filter(termFilter("animal", "cat")));
|
||||
indexAliasesService.add("dogs", filter(termFilter("animal", "dog")));
|
||||
|
@ -94,19 +95,41 @@ public class IndexAliasesServiceTests {
|
|||
assertThat(indexAliasesService.aliasFilter("cats", "all"), nullValue());
|
||||
assertThat(indexAliasesService.aliasFilter("all", "cats"), nullValue());
|
||||
|
||||
// Index itself should turn off al filters as well
|
||||
assertThat(indexAliasesService.aliasFilter("test", "cats"), nullValue());
|
||||
|
||||
// Unknown aliases should be ignored
|
||||
assertThat(indexAliasesService.aliasFilter("unknown", "cats").toString(), equalTo("FilterCacheFilterWrapper(animal:cat)"));
|
||||
assertThat(indexAliasesService.aliasFilter("unknown", "all"), nullValue());
|
||||
|
||||
indexAliasesService.remove("cats");
|
||||
assertThat(indexAliasesService.aliasFilter("cats"), nullValue());
|
||||
|
||||
indexAliasesService.add("cats", filter(termFilter("animal", "feline")));
|
||||
indexAliasesService.add("dogs", filter(termFilter("animal", "canine")));
|
||||
assertThat(indexAliasesService.aliasFilter("dogs", "cats").toString(), equalTo("BooleanFilter( FilterCacheFilterWrapper(animal:canine) FilterCacheFilterWrapper(animal:feline))"));
|
||||
}
|
||||
|
||||
@Test public void testAliasFilters() throws Exception {
|
||||
IndexAliasesService indexAliasesService = newIndexAliasesService();
|
||||
indexAliasesService.add("cats", filter(termFilter("animal", "cat")));
|
||||
indexAliasesService.add("dogs", filter(termFilter("animal", "dog")));
|
||||
|
||||
assertThat(indexAliasesService.aliasFilter(), nullValue());
|
||||
assertThat(indexAliasesService.aliasFilter("dogs").toString(), equalTo("FilterCacheFilterWrapper(animal:dog)"));
|
||||
assertThat(indexAliasesService.aliasFilter("dogs", "cats").toString(), equalTo("BooleanFilter( FilterCacheFilterWrapper(animal:dog) FilterCacheFilterWrapper(animal:cat))"));
|
||||
|
||||
indexAliasesService.add("cats", filter(termFilter("animal", "feline")));
|
||||
indexAliasesService.add("dogs", filter(termFilter("animal", "canine")));
|
||||
|
||||
assertThat(indexAliasesService.aliasFilter("dogs", "cats").toString(), equalTo("BooleanFilter( FilterCacheFilterWrapper(animal:canine) FilterCacheFilterWrapper(animal:feline))"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = InvalidAliasNameException.class) public void testRemovedAliasFilter() throws Exception {
|
||||
IndexAliasesService indexAliasesService = newIndexAliasesService();
|
||||
indexAliasesService.add("cats", filter(termFilter("animal", "cat")));
|
||||
indexAliasesService.remove("cats");
|
||||
indexAliasesService.aliasFilter("cats");
|
||||
}
|
||||
|
||||
|
||||
@Test(expectedExceptions = InvalidAliasNameException.class) public void testUnknownAliasFilter() throws Exception {
|
||||
IndexAliasesService indexAliasesService = newIndexAliasesService();
|
||||
indexAliasesService.add("cats", filter(termFilter("animal", "cat")));
|
||||
indexAliasesService.add("dogs", filter(termFilter("animal", "dog")));
|
||||
|
||||
indexAliasesService.aliasFilter("unknown");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,18 +22,25 @@ package org.elasticsearch.test.integration.aliases;
|
|||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.index.query.xcontent.QueryBuilders;
|
||||
import org.elasticsearch.index.query.xcontent.XContentFilterBuilder;
|
||||
import org.elasticsearch.indices.IndexMissingException;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
import org.elasticsearch.test.integration.AbstractNodesTests;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.client.Requests.*;
|
||||
import static org.elasticsearch.index.query.xcontent.FilterBuilders.termFilter;
|
||||
import static org.elasticsearch.common.collect.Sets.newHashSet;
|
||||
import static org.elasticsearch.index.query.xcontent.FilterBuilders.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
|
@ -135,6 +142,181 @@ public class IndexAliasesTests extends AbstractNodesTests {
|
|||
|
||||
}
|
||||
|
||||
@Test public void testSearchingFilteringAliasesSingleIndex() throws Exception {
|
||||
logger.info("--> creating index [test]");
|
||||
client1.admin().indices().create(createIndexRequest("test")).actionGet();
|
||||
|
||||
logger.info("--> running cluster_health");
|
||||
ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealthRequest().waitForGreenStatus()).actionGet();
|
||||
logger.info("--> done cluster_health, status " + clusterHealth.status());
|
||||
assertThat(clusterHealth.timedOut(), equalTo(false));
|
||||
assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN));
|
||||
|
||||
logger.info("--> adding filtering aliases to index [test]");
|
||||
client1.admin().indices().prepareAliases().addAlias("test", "alias1").execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test", "alias2").execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test", "foos", termFilter("name", "foo")).execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test", "bars", termFilter("name", "bar")).execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test", "tests", termFilter("name", "test")).execute().actionGet();
|
||||
Thread.sleep(300);
|
||||
|
||||
logger.info("--> indexing against [test]");
|
||||
client1.index(indexRequest("test").type("type1").id("1").source(source("1", "foo test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test").type("type1").id("2").source(source("2", "bar test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test").type("type1").id("3").source(source("3", "baz test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test").type("type1").id("4").source(source("4", "something else")).refresh(true)).actionGet();
|
||||
|
||||
logger.info("--> checking single filtering alias search");
|
||||
SearchResponse searchResponse = client1.prepareSearch("foos").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1");
|
||||
|
||||
searchResponse = client1.prepareSearch("tests").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "2", "3");
|
||||
|
||||
searchResponse = client1.prepareSearch("foos", "bars").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "2");
|
||||
|
||||
logger.info("--> checking single non-filtering alias search");
|
||||
searchResponse = client1.prepareSearch("alias1").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "2", "3", "4");
|
||||
|
||||
logger.info("--> checking non-filtering alias and filtering alias search");
|
||||
searchResponse = client1.prepareSearch("alias1", "foos").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "2", "3", "4");
|
||||
|
||||
logger.info("--> checking index and filtering alias search");
|
||||
searchResponse = client1.prepareSearch("test", "foos").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "2", "3", "4");
|
||||
}
|
||||
|
||||
@Test public void testSearchingFilteringAliasesTwoIndices() throws Exception {
|
||||
logger.info("--> creating index [test1]");
|
||||
client1.admin().indices().create(createIndexRequest("test1")).actionGet();
|
||||
|
||||
logger.info("--> creating index [test2]");
|
||||
client1.admin().indices().create(createIndexRequest("test2")).actionGet();
|
||||
|
||||
logger.info("--> running cluster_health");
|
||||
ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealthRequest().waitForGreenStatus()).actionGet();
|
||||
logger.info("--> done cluster_health, status " + clusterHealth.status());
|
||||
assertThat(clusterHealth.timedOut(), equalTo(false));
|
||||
assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN));
|
||||
|
||||
logger.info("--> adding filtering aliases to index [test1]");
|
||||
client1.admin().indices().prepareAliases().addAlias("test1", "aliasToTest1").execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test1", "aliasToTests").execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test1", "foos", termFilter("name", "foo")).execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test1", "bars", termFilter("name", "bar")).execute().actionGet();
|
||||
|
||||
logger.info("--> adding filtering aliases to index [test2]");
|
||||
client1.admin().indices().prepareAliases().addAlias("test2", "aliasToTest2").execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test2", "aliasToTests").execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test2", "foos", termFilter("name", "foo")).execute().actionGet();
|
||||
Thread.sleep(300);
|
||||
|
||||
logger.info("--> indexing against [test1]");
|
||||
client1.index(indexRequest("test1").type("type1").id("1").source(source("1", "foo test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test1").type("type1").id("2").source(source("2", "bar test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test1").type("type1").id("3").source(source("3", "baz test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test1").type("type1").id("4").source(source("4", "something else")).refresh(true)).actionGet();
|
||||
|
||||
logger.info("--> indexing against [test2]");
|
||||
client1.index(indexRequest("test2").type("type1").id("5").source(source("5", "foo test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test2").type("type1").id("6").source(source("6", "bar test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test2").type("type1").id("7").source(source("7", "baz test")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test2").type("type1").id("8").source(source("8", "something else")).refresh(true)).actionGet();
|
||||
|
||||
logger.info("--> checking filtering alias for two indices");
|
||||
SearchResponse searchResponse = client1.prepareSearch("foos").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "5");
|
||||
|
||||
logger.info("--> checking filtering alias for one index");
|
||||
searchResponse = client1.prepareSearch("bars").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "2");
|
||||
|
||||
logger.info("--> checking filtering alias for two indices and one complete index");
|
||||
searchResponse = client1.prepareSearch("foos", "test1").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "2", "3", "4", "5");
|
||||
|
||||
logger.info("--> checking filtering alias for two indices and non-filtering alias for one index");
|
||||
searchResponse = client1.prepareSearch("foos", "aliasToTest1").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "1", "2", "3", "4", "5");
|
||||
|
||||
logger.info("--> checking filtering alias for two indices and non-filtering alias for both indices");
|
||||
searchResponse = client1.prepareSearch("foos", "aliasToTests").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertThat(searchResponse.hits().totalHits(), equalTo(8L));
|
||||
}
|
||||
|
||||
@Test public void testSearchingFilteringAliasesMultipleIndices() throws Exception {
|
||||
logger.info("--> creating indices");
|
||||
client1.admin().indices().create(createIndexRequest("test1")).actionGet();
|
||||
client1.admin().indices().create(createIndexRequest("test2")).actionGet();
|
||||
client1.admin().indices().create(createIndexRequest("test3")).actionGet();
|
||||
|
||||
logger.info("--> running cluster_health");
|
||||
ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealthRequest().waitForGreenStatus()).actionGet();
|
||||
logger.info("--> done cluster_health, status " + clusterHealth.status());
|
||||
assertThat(clusterHealth.timedOut(), equalTo(false));
|
||||
assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN));
|
||||
|
||||
logger.info("--> adding aliases to indices");
|
||||
client1.admin().indices().prepareAliases().addAlias("test1", "alias12").execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test2", "alias12").execute().actionGet();
|
||||
|
||||
logger.info("--> adding filtering aliases to indices");
|
||||
client1.admin().indices().prepareAliases().addAlias("test1", "filter1", termFilter("name", "test1")).execute().actionGet();
|
||||
|
||||
client1.admin().indices().prepareAliases().addAlias("test2", "filter23", termFilter("name", "foo")).execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test3", "filter23", termFilter("name", "foo")).execute().actionGet();
|
||||
|
||||
client1.admin().indices().prepareAliases().addAlias("test1", "filter13", termFilter("name", "baz")).execute().actionGet();
|
||||
client1.admin().indices().prepareAliases().addAlias("test3", "filter13", termFilter("name", "baz")).execute().actionGet();
|
||||
|
||||
Thread.sleep(300);
|
||||
|
||||
logger.info("--> indexing against [test1]");
|
||||
client1.index(indexRequest("test1").type("type1").id("11").source(source("11", "foo test1")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test1").type("type1").id("12").source(source("12", "bar test1")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test1").type("type1").id("13").source(source("13", "baz test1")).refresh(true)).actionGet();
|
||||
|
||||
client1.index(indexRequest("test2").type("type1").id("21").source(source("21", "foo test2")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test2").type("type1").id("22").source(source("22", "bar test2")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test2").type("type1").id("23").source(source("23", "baz test2")).refresh(true)).actionGet();
|
||||
|
||||
client1.index(indexRequest("test3").type("type1").id("31").source(source("31", "foo test3")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test3").type("type1").id("32").source(source("32", "bar test3")).refresh(true)).actionGet();
|
||||
client1.index(indexRequest("test3").type("type1").id("33").source(source("33", "baz test3")).refresh(true)).actionGet();
|
||||
|
||||
logger.info("--> checking filtering alias for multiple indices");
|
||||
SearchResponse searchResponse = client1.prepareSearch("filter23", "filter13").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "21", "31", "13", "33");
|
||||
|
||||
searchResponse = client1.prepareSearch("filter23", "filter1").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "21", "31", "11", "12", "13");
|
||||
|
||||
searchResponse = client1.prepareSearch("filter13", "filter1").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "11", "12", "13", "33");
|
||||
|
||||
searchResponse = client1.prepareSearch("filter13", "filter1", "filter23").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "11", "12", "13", "21", "31", "33");
|
||||
|
||||
searchResponse = client1.prepareSearch("filter23", "filter13", "test2").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "21", "22", "23", "31", "13", "33");
|
||||
|
||||
searchResponse = client1.prepareSearch("filter23", "filter13", "test1", "test2").setQuery(QueryBuilders.matchAllQuery()).execute().actionGet();
|
||||
assertHits(searchResponse.hits(), "11", "12", "13", "21", "22", "23", "31", "33");
|
||||
|
||||
}
|
||||
|
||||
private void assertHits(SearchHits hits, String... ids) {
|
||||
assertThat(hits.totalHits(), equalTo((long) ids.length));
|
||||
Set<String> hitIds = newHashSet();
|
||||
for (SearchHit hit : hits.getHits()) {
|
||||
hitIds.add(hit.id());
|
||||
}
|
||||
assertThat(hitIds, containsInAnyOrder(ids));
|
||||
}
|
||||
|
||||
private String source(String id, String nameValue) {
|
||||
return "{ type1 : { \"id\" : \"" + id + "\", \"name\" : \"" + nameValue + "\" } }";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue