From d9d050e2f26fa1eb00aa370a33f46e7c221c3774 Mon Sep 17 00:00:00 2001 From: Dmitry Tikhonov Date: Thu, 29 Mar 2018 20:54:47 +0300 Subject: [PATCH] SOLR-9685 tag a query in JSON syntax Support following structure: {"#RCOLOR": { "term": { "f": "color","v": "blue"}}} RCOLOR will be tag name --- .../solr/request/json/JsonQueryConverter.java | 25 +- .../solr/search/json/TestJsonRequest.java | 274 +++++++++++++++++- 2 files changed, 284 insertions(+), 15 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/request/json/JsonQueryConverter.java b/solr/core/src/java/org/apache/solr/request/json/JsonQueryConverter.java index e732470749b9..8f8d04a890a2 100644 --- a/solr/core/src/java/org/apache/solr/request/json/JsonQueryConverter.java +++ b/solr/core/src/java/org/apache/solr/request/json/JsonQueryConverter.java @@ -68,8 +68,21 @@ private void buildLocalParams(StringBuilder builder, Object val, boolean isQPars throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error when parsing json query, expect only one query parser here, but found : "+map.keySet()); } + String qtype = map.keySet().iterator().next(); - Object subVal = map.get(qtype); + String tagName = null; + if (qtype.startsWith("#")) { + Object taggedQueryObject = map.get(qtype); + tagName = qtype.substring(1); + if (taggedQueryObject instanceof String) { + builder.append("{!tag=").append(tagName).append("}"); + builder.append(taggedQueryObject); + return; + } else if (taggedQueryObject instanceof Map) { + map = (Map) taggedQueryObject; + qtype = map.keySet().iterator().next(); + } + } // We don't want to introduce unnecessary variable at root level boolean useSubBuilder = builder.length() > 0; @@ -77,11 +90,17 @@ private void buildLocalParams(StringBuilder builder, Object val, boolean isQPars if (useSubBuilder) subBuilder = new StringBuilder(); - subBuilder = subBuilder.append("{!").append(qtype).append(' ');; + Object subVal = map.get(qtype); + subBuilder = subBuilder.append("{!").append(qtype).append(' '); + if (tagName != null) { + subBuilder.append("tag=").append(tagName).append(' '); + } buildLocalParams(subBuilder, subVal, false, additionalParams); subBuilder.append("}"); - if (useSubBuilder) builder.append('$').append(putParam(subBuilder.toString(), additionalParams)); + if (useSubBuilder) { + builder.append('$').append(putParam(subBuilder.toString(), additionalParams)); + } } else { for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); diff --git a/solr/core/src/test/org/apache/solr/search/json/TestJsonRequest.java b/solr/core/src/test/org/apache/solr/search/json/TestJsonRequest.java index 4f47f8a2652a..a90e8c9522b9 100644 --- a/solr/core/src/test/org/apache/solr/search/json/TestJsonRequest.java +++ b/solr/core/src/test/org/apache/solr/search/json/TestJsonRequest.java @@ -56,26 +56,22 @@ public void testLocalJsonRequest() throws Exception { doJsonRequest(Client.localClient, false); } + @Test + public void testLocalJsonRequestWithTags() throws Exception { + doJsonRequestWithTag(Client.localClient); + } + @Test public void testDistribJsonRequest() throws Exception { initServers(); initServers(); - Client client = servers.getClient( random().nextInt() ); - client.queryDefaults().set( "shards", servers.getShards() ); + Client client = servers.getClient(random().nextInt()); + client.queryDefaults().set("shards", servers.getShards()); doJsonRequest(client, true); } public static void doJsonRequest(Client client, boolean isDistrib) throws Exception { - client.deleteByQuery("*:*", null); - client.add(sdoc("id", "1", "cat_s", "A", "where_s", "NY"), null); - client.add(sdoc("id", "2", "cat_s", "B", "where_s", "NJ"), null); - client.add(sdoc("id", "3"), null); - client.commit(); - client.add(sdoc("id", "4", "cat_s", "A", "where_s", "NJ"), null); - client.add(sdoc("id", "5", "cat_s", "B", "where_s", "NJ"), null); - client.commit(); - client.add(sdoc("id", "6", "cat_s", "B", "where_s", "NY"), null); - client.commit(); + addDocs(client); // test json param @@ -401,4 +397,258 @@ public static void doJsonRequest(Client client, boolean isDistrib) throws Except } + public static void doJsonRequestWithTag(Client client) throws Exception { + addDocs(client); + + try { + client.testJQ( params("json","{" + + " query : '*:*'," + + " filter : { \"RCAT\" : \"cat_s:A\" }" + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:B, count:3}, {val:A, count:2} ] }" + + "}" + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("expect a json object")); + } + + client.testJQ(params("json", "{" + + " query : '*:*'," + + " filter : {" + + " \"#RCAT\" : {" + + " term : {" + + " f : cat_s," + + " v : A" + + " } " + + " } " + + " } " + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:B, count:3}, {val:A, count:2} ] }" + + "}" + ); + + client.testJQ( params("json","{" + + " query : '*:*'," + + " filter : { \"#RCAT\" : \"cat_s:A\" }" + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:B, count:3}, {val:A, count:2} ] }" + + "}" + ); + + client.testJQ( params("json","{" + + " query : '*:*'," + + " filter : [{ \"#RCAT\" : \"cat_s:A\" }] " + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:B, count:3}, {val:A, count:2} ] }" + + "}" + ); + + client.testJQ(params("json", "{" + + " query : '*:*'," + + " filter : {" + + " \"#RCAT\" : {" + + " term : {" + + " f : cat_s," + + " v : A" + + " } " + + " } " + + " } " + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:B, count:3}, {val:A, count:2} ] }" + + "}" + ); + + client.testJQ( params("json","{" + + " query : '*:*'," + + " filter : {" + + " term : {" + + " f : cat_s," + + " v : A" + + " } " + + " } " + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:A, count:2} ] }" + + "}" + ); + + client.testJQ( params("json","{" + + " query : '*:*'," + + " filter : {" + + " term : {" + + " f : cat_s," + + " v : A" + + " } " + + " } " + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:A, count:2} ] }" + + "}" + ); + + client.testJQ( params("json","{" + + " query : '*:*'," + + " filter : {" + + " \"#RCAT\" : {" + + " term : {" + + " f : cat_s," + + " v : A" + + " } " + + " } " + + " } " + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:A, count:2} ] }" + + "}" + ); + + client.testJQ( params("json","{" + + " query : {" + + " \"#RCAT\" : {" + + " term : {" + + " f : cat_s," + + " v : A" + + " } " + + " } " + + " } " + + "}", "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "}"), "facets=={ count:2, " + + " categories:{ buckets:[ {val:B, count:3}, {val:A, count:2} ] }" + + "}" + ); + + client.testJQ(params("json", "{" + + " query : '*:*'," + + " filter : [" + + "{ \"#RCAT\" : \"cat_s:A\" }," + + "{ \"#RWHERE\" : {" + + " term : {" + + " f : where_s," + + " v : NY" + + " } " + + " }" + + "}]}" + , "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "countries:{ type:terms, field:where_s, domain:{excludeTags:\"RWHERE\"} } " + + "ids:{ type:terms, field:id, domain:{excludeTags:[\"RCAT\", \"RWHERE\"]} } " + + "}"), "facets==" + "{\n" + + " \"count\":1,\n" + + " \"categories\":{\n" + + " \"buckets\":[{\n" + + " \"val\":\"A\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"B\",\n" + + " \"count\":1}]},\n" + + " \"countries\":{\n" + + " \"buckets\":[{\n" + + " \"val\":\"NJ\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"NY\",\n" + + " \"count\":1}]},\n" + + " \"ids\":{\n" + + " \"buckets\":[{\n" + + " \"val\":\"1\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"2\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"3\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"4\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"5\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"6\",\n" + + " \"count\":1}]}}}" + ); + + client.testJQ(params("json", "{" + + " query : '*:*'," + + " filter : [" + + "{ \"#RCAT,RCATSECONDTAG\" : \"cat_s:A\" }," + + "{ \"#RWHERE\" : {" + + " term : {" + + " f : where_s," + + " v : NY" + + " } " + + " }" + + "}]}" + , "json.facet", "{" + + "categories:{ type:terms, field:cat_s, domain:{excludeTags:\"RCAT\"} } " + + "countries:{ type:terms, field:where_s, domain:{excludeTags:\"RWHERE\"} } " + + "ids:{ type:terms, field:id, domain:{excludeTags:[\"RCATSECONDTAG\", \"RWHERE\"]} } " + + "}"), "facets==" + "{\n" + + " \"count\":1,\n" + + " \"categories\":{\n" + + " \"buckets\":[{\n" + + " \"val\":\"A\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"B\",\n" + + " \"count\":1}]},\n" + + " \"countries\":{\n" + + " \"buckets\":[{\n" + + " \"val\":\"NJ\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"NY\",\n" + + " \"count\":1}]},\n" + + " \"ids\":{\n" + + " \"buckets\":[{\n" + + " \"val\":\"1\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"2\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"3\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"4\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"5\",\n" + + " \"count\":1},\n" + + " {\n" + + " \"val\":\"6\",\n" + + " \"count\":1}]}}}" + ); + + } + + private static void addDocs(Client client) throws Exception { + client.deleteByQuery("*:*", null); + client.add(sdoc("id", "1", "cat_s", "A", "where_s", "NY"), null); + client.add(sdoc("id", "2", "cat_s", "B", "where_s", "NJ"), null); + client.add(sdoc("id", "3"), null); + client.commit(); + client.add(sdoc("id", "4", "cat_s", "A", "where_s", "NJ"), null); + client.add(sdoc("id", "5", "cat_s", "B", "where_s", "NJ"), null); + client.commit(); + client.add(sdoc("id", "6", "cat_s", "B", "where_s", "NY"), null); + client.commit(); + } + }