-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Term(s) Query/Filter : add _index support #7965
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,13 +19,23 @@ | |
|
||
package org.elasticsearch.index.mapper.internal; | ||
|
||
import com.google.common.base.Charsets; | ||
import org.apache.lucene.document.Document; | ||
import org.apache.lucene.document.Field; | ||
import org.apache.lucene.document.FieldType; | ||
import org.apache.lucene.index.FieldInfo.IndexOptions; | ||
import org.apache.lucene.index.Term; | ||
import org.apache.lucene.queries.TermFilter; | ||
import org.apache.lucene.search.Filter; | ||
import org.apache.lucene.search.PrefixFilter; | ||
import org.apache.lucene.search.Query; | ||
import org.apache.lucene.util.BytesRef; | ||
import org.elasticsearch.common.Nullable; | ||
import org.elasticsearch.common.Strings; | ||
import org.elasticsearch.common.lucene.BytesRefs; | ||
import org.elasticsearch.common.lucene.Lucene; | ||
import org.elasticsearch.common.lucene.search.Queries; | ||
import org.elasticsearch.common.lucene.search.XConstantScoreQuery; | ||
import org.elasticsearch.common.settings.ImmutableSettings; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.common.xcontent.XContentBuilder; | ||
|
@@ -34,8 +44,11 @@ | |
import org.elasticsearch.index.fielddata.FieldDataType; | ||
import org.elasticsearch.index.mapper.*; | ||
import org.elasticsearch.index.mapper.core.AbstractFieldMapper; | ||
import org.elasticsearch.index.query.QueryParseContext; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.Charset; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
|
@@ -58,7 +71,7 @@ public static class Defaults extends AbstractFieldMapper.Defaults { | |
public static final FieldType FIELD_TYPE = new FieldType(AbstractFieldMapper.Defaults.FIELD_TYPE); | ||
|
||
static { | ||
FIELD_TYPE.setIndexed(true); | ||
FIELD_TYPE.setIndexed(false); | ||
FIELD_TYPE.setTokenized(false); | ||
FIELD_TYPE.setStored(false); | ||
FIELD_TYPE.setOmitNorms(true); | ||
|
@@ -156,6 +169,62 @@ public String value(Object value) { | |
return value.toString(); | ||
} | ||
|
||
@Override | ||
public Filter termsFilter(List values, @Nullable QueryParseContext context) { | ||
if (fieldType.indexed() || context == null){ | ||
super.termsFilter(values, context); | ||
} | ||
for (Object value : values) { | ||
if (isSameIndex(value, context)) { | ||
return Queries.MATCH_ALL_FILTER; | ||
} | ||
} | ||
return Queries.MATCH_NO_FILTER; | ||
} | ||
|
||
|
||
/** | ||
* This termQuery impl looks at the context to determine the index that is being queried and | ||
* then creates returns a MATCH_ALL_FILTER or MATCH_NO_FILTER if the value matches this index | ||
* this can be useful if aliases or wildcards are used but the aim is to restrict the query to specific indices | ||
*/ | ||
@Override | ||
public Query termQuery(Object value, @Nullable QueryParseContext context) { | ||
if (fieldType.indexed() || context == null) { | ||
return super.termQuery(value, context); | ||
} | ||
if (isSameIndex(value, context)) { | ||
return new XConstantScoreQuery(Queries.MATCH_ALL_FILTER); | ||
} else { | ||
return new XConstantScoreQuery(Queries.MATCH_NO_FILTER); | ||
} | ||
|
||
} | ||
|
||
private boolean isSameIndex(Object value, QueryParseContext context) { | ||
if (value instanceof BytesRef) { | ||
BytesRef indexNameRef = new BytesRef(context.index().getName().getBytes(Charsets.UTF_8)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can directly do |
||
return (indexNameRef.bytesEquals((BytesRef) value)); | ||
} else if (value instanceof String) { | ||
return context.index().getName().equals(value); | ||
} else { | ||
return context.index().getName().equals(value.toString()); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need the |
||
} | ||
|
||
@Override | ||
public Filter termFilter(Object value, @Nullable QueryParseContext context) { | ||
if (fieldType.indexed() || context == null) { | ||
return new TermFilter(names().createIndexNameTerm(BytesRefs.toBytesRef(value))); | ||
} | ||
if (isSameIndex(value, context)) { | ||
return Queries.MATCH_ALL_FILTER; | ||
} else { | ||
return Queries.MATCH_NO_FILTER; | ||
} | ||
} | ||
|
||
|
||
@Override | ||
public void preParse(ParseContext context) throws IOException { | ||
// we pre parse it and not in parse, since its not part of the root object | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* 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.index.query; | ||
|
||
import org.junit.Test; | ||
|
||
|
||
import org.elasticsearch.action.search.SearchRequest; | ||
import org.elasticsearch.action.search.SearchResponse; | ||
import org.elasticsearch.common.bytes.BytesArray; | ||
import org.elasticsearch.common.bytes.BytesReference; | ||
import org.junit.Test; | ||
|
||
import java.util.concurrent.ExecutionException; | ||
|
||
import static org.hamcrest.Matchers.*; | ||
|
||
/** | ||
*/ | ||
public class TermFilterTests extends TermQueryTests { | ||
|
||
@Test | ||
public void testIndexTermFilter() throws InterruptedException, ExecutionException { | ||
createIndex( "test1", "test2"); | ||
ensureGreen( "test1", "test2"); | ||
|
||
long docsInTest1 = scaledRandomIntBetween(10,100); | ||
long docsInTest2 = scaledRandomIntBetween(10,100); | ||
|
||
indexDocsToIndex("test1", docsInTest1); | ||
indexDocsToIndex("test2", docsInTest2); | ||
|
||
{ | ||
SearchRequest searchRequest = new SearchRequest(); | ||
searchRequest.indices("_all"); | ||
String query = "{\"query\":\n" + | ||
"{\n" + | ||
" \"filtered\": {\n" + | ||
" \"query\": {\n" + | ||
" \"match_all\": {}\n" + | ||
" },\n" + | ||
" \"filter\": {\n" + | ||
" \"term\": { \"_index\": { \"value\": \"test1\" }}\n" + | ||
" }\n" + | ||
" }\n" + | ||
"} }"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be easier with the Java API? |
||
|
||
BytesReference bytesRef = new BytesArray(query); | ||
searchRequest.source(bytesRef, false); | ||
SearchResponse response = client().search(searchRequest).get(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add an |
||
|
||
assertThat(response.getHits().totalHits(), is(docsInTest1)); | ||
} | ||
|
||
{ | ||
SearchRequest searchRequest = new SearchRequest(); | ||
searchRequest.indices("_all"); | ||
|
||
String query = "{\"query\":\n" + | ||
"{\n" + | ||
" \"filtered\": {\n" + | ||
" \"query\": {\n" + | ||
" \"match_all\": {}\n" + | ||
" },\n" + | ||
" \"filter\": {\n" + | ||
" \"term\": { \"_index\": { \"value\": \"test2\" }}\n" + | ||
" }\n" + | ||
" }\n" + | ||
"} }"; | ||
|
||
BytesReference bytesRef = new BytesArray(query); | ||
searchRequest.source(bytesRef, false); | ||
SearchResponse response = client().search(searchRequest).get(); | ||
|
||
assertThat(response.getHits().totalHits(), is(docsInTest2)); | ||
} | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* 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.index.query; | ||
|
||
import org.elasticsearch.action.index.IndexRequestBuilder; | ||
import org.elasticsearch.action.search.SearchRequest; | ||
import org.elasticsearch.action.search.SearchResponse; | ||
import org.elasticsearch.common.bytes.BytesArray; | ||
import org.elasticsearch.common.bytes.BytesReference; | ||
import org.elasticsearch.test.ElasticsearchIntegrationTest; | ||
import org.junit.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
import static org.hamcrest.Matchers.*; | ||
|
||
public class TermQueryTests extends ElasticsearchIntegrationTest{ | ||
|
||
@Test | ||
public void testIndexTermQuery() throws InterruptedException, ExecutionException { | ||
createIndex( "test1" , "test2"); | ||
ensureGreen( "test1", "test2"); | ||
|
||
long docsInTest1 = scaledRandomIntBetween(10,100); | ||
long docsInTest2 = scaledRandomIntBetween(10,100); | ||
|
||
indexDocsToIndex("test1", docsInTest1); | ||
indexDocsToIndex("test2", docsInTest2); | ||
|
||
{ | ||
SearchRequest searchRequest = new SearchRequest(); | ||
searchRequest.indices("_all"); | ||
|
||
String query = "{ \"query\" : " + | ||
"{ \"term\": " + | ||
"{ \"_index\" : " + | ||
"{\"value\" : \"test1\"} " + | ||
"} } } "; | ||
BytesReference bytesRef = new BytesArray(query); | ||
searchRequest.source(bytesRef, false); | ||
SearchResponse response = client().search(searchRequest).get(); | ||
|
||
assertThat(response.getHits().totalHits(), is(docsInTest1)); | ||
} | ||
|
||
{ | ||
SearchRequest searchRequest = new SearchRequest(); | ||
searchRequest.indices("_all"); | ||
|
||
String query = "{ \"query\" : " + | ||
"{ \"term\": " + | ||
"{ \"_index\" : " + | ||
"{\"value\" : \"test2\"} " + | ||
"} } } "; | ||
BytesReference bytesRef = new BytesArray(query); | ||
searchRequest.source(bytesRef, false); | ||
SearchResponse response = client().search(searchRequest).get(); | ||
|
||
assertThat(response.getHits().totalHits(), is(docsInTest2)); | ||
} | ||
|
||
} | ||
|
||
protected void indexDocsToIndex(String index, long count) throws InterruptedException, ExecutionException { | ||
List<IndexRequestBuilder> builders = new ArrayList<>(); | ||
|
||
for (int i = 0; i < count; ++i) { | ||
builders.add(client().prepareIndex(index, "type", "" + (i + 1) ).setSource("{\"theField\":\"foo\"}")); | ||
} | ||
|
||
indexRandom(true,builders); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to break multi-version clusters since we only print the difference from the default mapping in toXContent. I think this should remain true by default and the termQuery/termsFilter methods below should check that the field is indexed AND enabled?