diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/JSONQueryBuilder.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/JSONQueryBuilder.java new file mode 100644 index 00000000000..5805b29d386 --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/JSONQueryBuilder.java @@ -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 : + *
+ * {@code
+ *      BoolQueryBuilder bool = new BoolQueryBuilder();
+ *      bool.must(new JSONQueryBuilder("{\"term\": {\"field\":\"value\"}}");
+ *      bool.must(new TermQueryBuilder("field2","value2");
+ * }
+ * 
+ * + * @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(); + } +} diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/JSONQueryParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/JSONQueryParser.java new file mode 100644 index 00000000000..1dbdc451258 --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/JSONQueryParser.java @@ -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; + } +} diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryBuilders.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryBuilders.java index b1696844e52..2bfa6a64127 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryBuilders.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryBuilders.java @@ -611,6 +611,10 @@ public abstract class QueryBuilders { return new PrefixFilterBuilder(name, prefix); } + public static JSONQueryBuilder json(String jsonString) { + return new JSONQueryBuilder(jsonString); + } + private QueryBuilders() { } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/indices/query/IndicesQueriesRegistry.java b/modules/elasticsearch/src/main/java/org/elasticsearch/indices/query/IndicesQueriesRegistry.java index 0c1c8f4b411..e899397cbab 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/indices/query/IndicesQueriesRegistry.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/indices/query/IndicesQueriesRegistry.java @@ -67,6 +67,7 @@ public class IndicesQueriesRegistry { addQueryParser(queryParsers, new MoreLikeThisFieldQueryParser()); addQueryParser(queryParsers, new FuzzyLikeThisQueryParser()); addQueryParser(queryParsers, new FuzzyLikeThisFieldQueryParser()); + addQueryParser(queryParsers, new JSONQueryParser()); this.queryParsers = ImmutableMap.copyOf(queryParsers); Map filterParsers = Maps.newHashMap(); diff --git a/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java b/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java index 5587256e916..6b5e2665aaa 100644 --- a/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java +++ b/modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java @@ -22,6 +22,9 @@ package org.elasticsearch.test.integration.search.query; 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.test.integration.AbstractNodesTests; import org.testng.annotations.AfterClass; 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(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)); + + } + }