Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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);
Copy link
Contributor

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?

FIELD_TYPE.setTokenized(false);
FIELD_TYPE.setStored(false);
FIELD_TYPE.setOmitNorms(true);
Expand Down Expand Up @@ -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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can directly do BytesRef indexNameRef = new BytesRef(context.index().getName())

return (indexNameRef.bytesEquals((BytesRef) value));
} else if (value instanceof String) {
return context.index().getName().equals(value);
} else {
return context.index().getName().equals(value.toString());
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need the instanceof String check since String.toString returns itself

}

@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
Expand Down
97 changes: 97 additions & 0 deletions src/test/java/org/elasticsearch/index/query/TermFilterTests.java
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" +
"} }";
Copy link
Contributor

Choose a reason for hiding this comment

The 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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an assertSearchResponse here and in other tests? In case the count below is not correct, this will help make sure that no shards were reported as not successful


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));
}

}

}
91 changes: 91 additions & 0 deletions src/test/java/org/elasticsearch/index/query/TermQueryTests.java
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);
}
}
Loading