SOLR-9685: #tagging in JSON query syntax

This commit is contained in:
yonik 2018-05-27 16:22:16 -04:00
parent fd929c1d60
commit e5998fcb5d
3 changed files with 174 additions and 15 deletions

View File

@ -128,6 +128,12 @@ New Features
requests will fail when the coordinating node can't communicate with ZooKeeper,
by setting the "shards.tolerant" param to "requireZkConnected". (Steve Rowe)
* SOLR-9685: #Tagging queries in JSON Query DSL, equivalent to LocalParams based query/filter
tagging. Multiple tags are comma separated.
LocalParams Example : {!tag=colorfilt}color:blue
Equivalent JSON Example : { "#colorfilt" : "color:blue" }
(Dmitry Tikhonov, Mikhail Khludnev, yonik)
Bug Fixes
----------------------

View File

@ -68,8 +68,21 @@ class JsonQueryConverter {
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<String, Object>) 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 @@ class JsonQueryConverter {
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<String, Object> entry : map.entrySet()) {
String key = entry.getKey();

View File

@ -56,9 +56,13 @@ public class TestJsonRequest extends SolrTestCaseHS {
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() );
@ -66,17 +70,7 @@ public class TestJsonRequest extends SolrTestCaseHS {
}
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
client.testJQ( params("json","{query:'cat_s:A'}")
@ -401,4 +395,144 @@ public class TestJsonRequest extends SolrTestCaseHS {
}
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("no # no tag");
} catch (Exception e) {
assertTrue(e.getMessage().contains("expect a json object"));
}
final String taggedQ = "{" +
" \"#RCAT\" : " + (random().nextBoolean() ?
"{" +
" term : {" +
" f : cat_s," +
" v : A" +
" } " +
" } "
: "\"cat_s:A\"")+
" } ";
boolean queryAndFilter = random().nextBoolean() ;
client.testJQ(params("json", "{" +
" query :" + ( queryAndFilter ? " '*:*', filter : " : "")
+ (!queryAndFilter || random().nextBoolean() ? taggedQ : "["+taggedQ+"]" )+
"}", "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"
+( random().nextBoolean() ? ", domain:{excludeTags:\"RCAT\"} ": " ")
+ "} " +
"}"), "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} ] }" +
"}"
);
boolean multiTag = random().nextBoolean();
client.testJQ(params("json", "{" +
" query : '*:*'," +
" filter : [" +
"{ \"#RCAT"+(multiTag ? ",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:[\""+ (multiTag ? "RCATSECONDTAG":"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}]}}}"
);
}
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();
}
}