Adds a JSONQueryBuilder which allows using a JSON query string through the Java builder API.

This commit is contained in:
melix 2011-07-12 14:37:44 +02:00 committed by kimchy
parent 1033249f0c
commit b627ba06c6
5 changed files with 166 additions and 0 deletions

View File

@ -0,0 +1,74 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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;
/**
* Created by IntelliJ IDEA.
* User: cedric
* Date: 12/07/11
* Time: 11:30
*/
import org.apache.lucene.util.UnicodeUtil;
import org.elasticsearch.common.jackson.JsonParser;
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
* to use the Java Builder API but still have JSON query strings at hand that you want to combine with other
* query builders.
*
* Example usage in a boolean query :
* <pre>
* {@code
* BoolQueryBuilder bool = new BoolQueryBuilder();
* bool.must(new JSONQueryBuilder("{\"term\": {\"field\":\"value\"}}");
* bool.must(new TermQueryBuilder("field2","value2");
* }
* </pre>
*
* @author Cedric Champeau
*/
public class JSONQueryBuilder extends BaseQueryBuilder {
private final String jsonQuery;
/**
* Builds a JSONQueryBuilder using the provided JSON query string.
* @param jsonQuery
*/
public JSONQueryBuilder(String jsonQuery) {
this.jsonQuery = jsonQuery;
}
@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.endObject();
}
}

View File

@ -0,0 +1,59 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.apache.lucene.search.Query;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
/**
* Query parser for JSON Queries.
*
* @author Cedric Champeau
*/
public class JSONQueryParser implements QueryParser {
public static final String NAME = "json";
@Inject public JSONQueryParser() {
}
@Override public String[] names() {
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();
}
}
return query;
}
}

View File

@ -611,6 +611,10 @@ public abstract class QueryBuilders {
return new PrefixFilterBuilder(name, prefix); return new PrefixFilterBuilder(name, prefix);
} }
public static JSONQueryBuilder json(String jsonString) {
return new JSONQueryBuilder(jsonString);
}
private QueryBuilders() { private QueryBuilders() {
} }

View File

@ -67,6 +67,7 @@ public class IndicesQueriesRegistry {
addQueryParser(queryParsers, new MoreLikeThisFieldQueryParser()); addQueryParser(queryParsers, new MoreLikeThisFieldQueryParser());
addQueryParser(queryParsers, new FuzzyLikeThisQueryParser()); addQueryParser(queryParsers, new FuzzyLikeThisQueryParser());
addQueryParser(queryParsers, new FuzzyLikeThisFieldQueryParser()); addQueryParser(queryParsers, new FuzzyLikeThisFieldQueryParser());
addQueryParser(queryParsers, new JSONQueryParser());
this.queryParsers = ImmutableMap.copyOf(queryParsers); this.queryParsers = ImmutableMap.copyOf(queryParsers);
Map<String, FilterParser> filterParsers = Maps.newHashMap(); Map<String, FilterParser> filterParsers = Maps.newHashMap();

View File

@ -22,6 +22,9 @@ package org.elasticsearch.test.integration.search.query;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.ImmutableSettings; 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.test.integration.AbstractNodesTests; import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
@ -276,4 +279,29 @@ public class SimpleQueryTests extends AbstractNodesTests {
assertThat(searchResponse.hits().getAt(0).id(), anyOf(equalTo("3"), equalTo("4"))); assertThat(searchResponse.hits().getAt(0).id(), anyOf(equalTo("3"), equalTo("4")));
assertThat(searchResponse.hits().getAt(1).id(), anyOf(equalTo("3"), equalTo("4"))); assertThat(searchResponse.hits().getAt(1).id(), anyOf(equalTo("3"), equalTo("4")));
} }
@Test public void passQueryAsJSONStringTest() throws Exception {
try {
client.admin().indices().prepareDelete("test").execute().actionGet();
} catch (Exception e) {
// ignore
}
client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 1)).execute().actionGet();
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();
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
BoolQueryBuilder bool = new BoolQueryBuilder();
bool.must(json);
bool.must(new TermQueryBuilder("field2", "value2_1"));
searchResponse = client.prepareSearch().setQuery(json).execute().actionGet();
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
}
} }