Query DSL: indices filter type, closes #1787.
This commit is contained in:
parent
42541f7354
commit
6046e7c6eb
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.common.lucene.search;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.DocIdSet;
|
||||
import org.apache.lucene.search.Filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A filter that matches no docs.
|
||||
*/
|
||||
public class MatchNoDocsFilter extends Filter {
|
||||
|
||||
@Override
|
||||
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj.getClass() == this.getClass()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MatchNoDocsFilter";
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ public class Queries {
|
|||
* A match all docs filter. Note, requires no caching!.
|
||||
*/
|
||||
public final static Filter MATCH_ALL_FILTER = new MatchAllDocsFilter();
|
||||
public final static Filter MATCH_NO_FILTER = new MatchNoDocsFilter();
|
||||
|
||||
private final static Field disjuncts;
|
||||
|
||||
|
|
|
@ -383,6 +383,10 @@ public abstract class FilterBuilders {
|
|||
return new NotFilterBuilder(filter);
|
||||
}
|
||||
|
||||
public static IndicesFilterBuilder indicesFilter(FilterBuilder filter, String... indices) {
|
||||
return new IndicesFilterBuilder(filter, indices);
|
||||
}
|
||||
|
||||
private FilterBuilders() {
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.index.query;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A filter that will execute the wrapped filter only for the specified indices, and "match_all" when
|
||||
* it does not match those indices (by default).
|
||||
*/
|
||||
public class IndicesFilterBuilder extends BaseFilterBuilder {
|
||||
|
||||
private final FilterBuilder filterBuilder;
|
||||
|
||||
private final String[] indices;
|
||||
|
||||
private String sNoMatchFilter;
|
||||
private FilterBuilder noMatchFilter;
|
||||
|
||||
private String filterName;
|
||||
|
||||
public IndicesFilterBuilder(FilterBuilder filterBuilder, String... indices) {
|
||||
this.filterBuilder = filterBuilder;
|
||||
this.indices = indices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the no match filter, can either be <tt>all</tt> or <tt>none</tt>.
|
||||
*/
|
||||
public IndicesFilterBuilder noMatchFilter(String type) {
|
||||
this.sNoMatchFilter = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filter to use when it executes on an index that does not match the indices provided.
|
||||
*/
|
||||
public IndicesFilterBuilder noMatchFilter(FilterBuilder noMatchFilter) {
|
||||
this.noMatchFilter = noMatchFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filter name for the filter that can be used when searching for matched_filters per hit.
|
||||
*/
|
||||
public IndicesFilterBuilder filterName(String filterName) {
|
||||
this.filterName = filterName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(IndicesFilterParser.NAME);
|
||||
builder.field("filter");
|
||||
filterBuilder.toXContent(builder, params);
|
||||
builder.field("indices", indices);
|
||||
if (noMatchFilter != null) {
|
||||
builder.field("no_match_filter");
|
||||
noMatchFilter.toXContent(builder, params);
|
||||
} else if (sNoMatchFilter != null) {
|
||||
builder.field("no_match_filter", sNoMatchFilter);
|
||||
}
|
||||
|
||||
if (filterName != null) {
|
||||
builder.field("_name", filterName);
|
||||
}
|
||||
|
||||
builder.endObject();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.index.query;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class IndicesFilterParser implements FilterParser {
|
||||
|
||||
public static final String NAME = "indices";
|
||||
|
||||
@Nullable
|
||||
private final ClusterService clusterService;
|
||||
|
||||
@Inject
|
||||
public IndicesFilterParser(@Nullable ClusterService clusterService) {
|
||||
this.clusterService = clusterService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] names() {
|
||||
return new String[]{NAME};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
|
||||
Filter filter = null;
|
||||
Set<String> indices = Sets.newHashSet();
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
Filter noMatchFilter = Queries.MATCH_ALL_FILTER;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if ("filter".equals(currentFieldName)) {
|
||||
filter = parseContext.parseInnerFilter();
|
||||
} else if ("no_match_filter".equals(currentFieldName)) {
|
||||
noMatchFilter = parseContext.parseInnerFilter();
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] filter does not support [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if ("indices".equals(currentFieldName)) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
String value = parser.textOrNull();
|
||||
if (value == null) {
|
||||
throw new QueryParsingException(parseContext.index(), "No value specified for term filter");
|
||||
}
|
||||
indices.add(value);
|
||||
}
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] filter does not support [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("index".equals(currentFieldName)) {
|
||||
indices.add(parser.text());
|
||||
} else if ("no_match_filter".equals(currentFieldName)) {
|
||||
String type = parser.text();
|
||||
if ("all".equals(type)) {
|
||||
noMatchFilter = Queries.MATCH_ALL_FILTER;
|
||||
} else if ("none".equals(type)) {
|
||||
noMatchFilter = Queries.MATCH_NO_FILTER;
|
||||
}
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] filter does not support [" + currentFieldName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filter == null) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'filter' element");
|
||||
}
|
||||
if (indices.isEmpty()) {
|
||||
throw new QueryParsingException(parseContext.index(), "[indices] requires 'indices' element");
|
||||
}
|
||||
|
||||
String[] concreteIndices = indices.toArray(new String[indices.size()]);
|
||||
if (clusterService != null) {
|
||||
MetaData metaData = clusterService.state().metaData();
|
||||
concreteIndices = metaData.concreteIndices(indices.toArray(new String[indices.size()]), true, true);
|
||||
}
|
||||
|
||||
for (String index : concreteIndices) {
|
||||
if (Regex.simpleMatch(index, parseContext.index().name())) {
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
return noMatchFilter;
|
||||
}
|
||||
}
|
|
@ -100,6 +100,7 @@ public class IndicesQueriesRegistry {
|
|||
addFilterParser(filterParsers, new MatchAllFilterParser());
|
||||
addFilterParser(filterParsers, new ExistsFilterParser());
|
||||
addFilterParser(filterParsers, new MissingFilterParser());
|
||||
addFilterParser(filterParsers, new IndicesFilterParser(clusterService));
|
||||
this.filterParsers = ImmutableMap.copyOf(filterParsers);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue