rename json query to wrapper query, and optimize it to not parse it twice, once on creation, and once on parsing to build lucene queries
This commit is contained in:
parent
cfc45b0ab9
commit
c2584baf86
|
@ -438,6 +438,12 @@ public final class XContentBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public XContentBuilder field(String name, byte[] value, int offset, int length) throws IOException {
|
||||
field(name);
|
||||
generator.writeBinary(value, offset, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
public XContentBuilder field(String name, Map<String, Object> value) throws IOException {
|
||||
field(name);
|
||||
value(value);
|
||||
|
@ -486,24 +492,6 @@ public final class XContentBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public XContentBuilder field(String name, Object... value) throws IOException {
|
||||
startArray(name);
|
||||
for (Object o : value) {
|
||||
value(o);
|
||||
}
|
||||
endArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public XContentBuilder field(XContentBuilderString name, Object... value) throws IOException {
|
||||
startArray(name);
|
||||
for (Object o : value) {
|
||||
value(o);
|
||||
}
|
||||
endArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public XContentBuilder field(String name, int... value) throws IOException {
|
||||
startArray(name);
|
||||
for (Object o : value) {
|
||||
|
@ -905,6 +893,14 @@ public final class XContentBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public XContentBuilder value(byte[] value, int offset, int length) throws IOException {
|
||||
if (value == null) {
|
||||
return nullValue();
|
||||
}
|
||||
generator.writeBinary(value, offset, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
public XContentBuilder map(Map<String, Object> map) throws IOException {
|
||||
if (map == null) {
|
||||
return nullValue();
|
||||
|
|
|
@ -611,8 +611,18 @@ public abstract class QueryBuilders {
|
|||
return new PrefixFilterBuilder(name, prefix);
|
||||
}
|
||||
|
||||
public static JSONQueryBuilder json(String jsonString) {
|
||||
return new JSONQueryBuilder(jsonString);
|
||||
/**
|
||||
* A Query builder which allows building a query thanks to a JSON string or binary data.
|
||||
*/
|
||||
public static WrapperQueryBuilder wrapperQuery(String source) {
|
||||
return new WrapperQueryBuilder(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Query builder which allows building a query thanks to a JSON string or binary data.
|
||||
*/
|
||||
public static WrapperQueryBuilder wrapperQuery(byte[] source, int offset, int length) {
|
||||
return new WrapperQueryBuilder(source, offset, length);
|
||||
}
|
||||
|
||||
private QueryBuilders() {
|
||||
|
|
|
@ -25,18 +25,13 @@ package org.elasticsearch.index.query;
|
|||
* Time: 11:30
|
||||
*/
|
||||
|
||||
import org.apache.lucene.util.UnicodeUtil;
|
||||
import org.elasticsearch.common.jackson.JsonParser;
|
||||
import org.elasticsearch.common.base.Charsets;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A Query builder which allows building a query thanks to a JSON string. This is useful when you want
|
||||
* A Query builder which allows building a query thanks to a JSON string or binary data. This is useful when you want
|
||||
* to use the Java Builder API but still have JSON query strings at hand that you want to combine with other
|
||||
* query builders.
|
||||
*
|
||||
|
@ -44,31 +39,37 @@ import java.io.IOException;
|
|||
* <pre>
|
||||
* {@code
|
||||
* BoolQueryBuilder bool = new BoolQueryBuilder();
|
||||
* bool.must(new JSONQueryBuilder("{\"term\": {\"field\":\"value\"}}");
|
||||
* bool.must(new WrapperQueryBuilder("{\"term\": {\"field\":\"value\"}}");
|
||||
* bool.must(new TermQueryBuilder("field2","value2");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Cedric Champeau
|
||||
*/
|
||||
public class JSONQueryBuilder extends BaseQueryBuilder {
|
||||
public class WrapperQueryBuilder extends BaseQueryBuilder {
|
||||
|
||||
private final String jsonQuery;
|
||||
private final byte[] source;
|
||||
private final int offset;
|
||||
private final int length;
|
||||
|
||||
/**
|
||||
* Builds a JSONQueryBuilder using the provided JSON query string.
|
||||
* @param jsonQuery
|
||||
*/
|
||||
public JSONQueryBuilder(String jsonQuery) {
|
||||
this.jsonQuery = jsonQuery;
|
||||
public WrapperQueryBuilder(String source) {
|
||||
this.source = source.getBytes(Charsets.UTF_8);
|
||||
this.offset = 0;
|
||||
this.length = source.length();
|
||||
}
|
||||
|
||||
public WrapperQueryBuilder(byte[] source, int offset, int length) {
|
||||
this.source = source;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@Override protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(JSONQueryParser.NAME);
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(jsonQuery);
|
||||
parser.nextToken();
|
||||
builder.field("value");
|
||||
builder.copyCurrentStructure(parser);
|
||||
builder.startObject(WrapperQueryParser.NAME);
|
||||
builder.field("query", source, offset, length);
|
||||
builder.endObject();
|
||||
}
|
||||
}
|
|
@ -21,39 +21,41 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Query parser for JSON Queries.
|
||||
*
|
||||
* @author Cedric Champeau
|
||||
*/
|
||||
public class JSONQueryParser implements QueryParser {
|
||||
public class WrapperQueryParser implements QueryParser {
|
||||
|
||||
public static final String NAME = "json";
|
||||
public static final String NAME = "wrapper";
|
||||
|
||||
@Inject public JSONQueryParser() {
|
||||
@Inject public WrapperQueryParser() {
|
||||
}
|
||||
|
||||
@Override public String[] names() {
|
||||
return new String[] {NAME};
|
||||
return new String[]{NAME};
|
||||
}
|
||||
|
||||
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
System.out.println("parseContext = " + parseContext);
|
||||
XContentParser parser = parseContext.parser();
|
||||
XContentParser.Token token;
|
||||
Query query = null;
|
||||
String currentFieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT && "value".equals(currentFieldName)) {
|
||||
query = parseContext.parseInnerQuery();
|
||||
}
|
||||
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
assert token == XContentParser.Token.FIELD_NAME;
|
||||
String fieldName = parser.currentName();
|
||||
assert fieldName.equals("query");
|
||||
parser.nextToken();
|
||||
|
||||
byte[] querySource = parser.binaryValue();
|
||||
XContentParser qSourceParser = XContentFactory.xContent(querySource).createParser(querySource);
|
||||
try {
|
||||
return SearchContext.current().queryParserService().parse(qSourceParser).query();
|
||||
} finally {
|
||||
qSourceParser.close();
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
|
@ -67,7 +67,7 @@ public class IndicesQueriesRegistry {
|
|||
addQueryParser(queryParsers, new MoreLikeThisFieldQueryParser());
|
||||
addQueryParser(queryParsers, new FuzzyLikeThisQueryParser());
|
||||
addQueryParser(queryParsers, new FuzzyLikeThisFieldQueryParser());
|
||||
addQueryParser(queryParsers, new JSONQueryParser());
|
||||
addQueryParser(queryParsers, new WrapperQueryParser());
|
||||
this.queryParsers = ImmutableMap.copyOf(queryParsers);
|
||||
|
||||
Map<String, FilterParser> filterParsers = Maps.newHashMap();
|
||||
|
|
|
@ -23,8 +23,8 @@ import org.elasticsearch.action.search.SearchResponse;
|
|||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.JSONQueryBuilder;
|
||||
import org.elasticsearch.index.query.TermQueryBuilder;
|
||||
import org.elasticsearch.index.query.WrapperQueryBuilder;
|
||||
import org.elasticsearch.test.integration.AbstractNodesTests;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
@ -291,15 +291,15 @@ public class SimpleQueryTests extends AbstractNodesTests {
|
|||
|
||||
client.prepareIndex("test", "type1", "1").setSource("field1", "value1_1", "field2", "value2_1").setRefresh(true).execute().actionGet();
|
||||
|
||||
JSONQueryBuilder json = new JSONQueryBuilder("{ \"term\" : { \"field1\" : \"value1_1\" } }");
|
||||
SearchResponse searchResponse = client.prepareSearch().setQuery(json).execute().actionGet();
|
||||
WrapperQueryBuilder wrapper = new WrapperQueryBuilder("{ \"term\" : { \"field1\" : \"value1_1\" } }");
|
||||
SearchResponse searchResponse = client.prepareSearch().setQuery(wrapper).execute().actionGet();
|
||||
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
|
||||
|
||||
BoolQueryBuilder bool = new BoolQueryBuilder();
|
||||
bool.must(json);
|
||||
bool.must(wrapper);
|
||||
bool.must(new TermQueryBuilder("field2", "value2_1"));
|
||||
|
||||
searchResponse = client.prepareSearch().setQuery(json).execute().actionGet();
|
||||
searchResponse = client.prepareSearch().setQuery(wrapper).execute().actionGet();
|
||||
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue