From 8fba8eba1348a27b8ecabab4c2bab669c5054065 Mon Sep 17 00:00:00 2001 From: Mikhail Khludnev Date: Fri, 3 Jan 2020 23:22:21 +0300 Subject: [PATCH] SOLR-12490: Introducing json.queries to define many named queries in Query DSL. --- solr/CHANGES.txt | 6 +- .../apache/solr/request/json/RequestUtil.java | 74 +++++++++++-------- .../solr/search/facet/TestJsonFacets.java | 28 ++++++- 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 10e453320f9..44cec922161 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -153,12 +153,14 @@ Upgrade Notes If you prefer to keep the old (but insecure) serialization strategy, you can start your nodes using the property: `-Dsolr.useUnsafeOverseerResponse=true`. Keep in mind that this will be removed in future version of Solr. - * SOLR-13808: add cache=false into uderneath BoolQParser's filter clause or {"bool":{"filter":..}} to avoid caching in + * SOLR-13808: add cache=false into underneath BoolQParser's filter clause or {"bool":{"filter":..}} to avoid caching in filterCache. (Mikhail Khludnev) New Features --------------------- -(No changes) + * SOLR-12490: Introducing json.queries in JSON Request API. Every property of this object holds one or many named + Query DSL queries. It's optional and doesn't impact response without explicit referencing these queries by names + (Anatolii Siuniaev via Mikhail Khludnev) Improvements --------------------- diff --git a/solr/core/src/java/org/apache/solr/request/json/RequestUtil.java b/solr/core/src/java/org/apache/solr/request/json/RequestUtil.java index 4925a417449..87ba244290d 100644 --- a/solr/core/src/java/org/apache/solr/request/json/RequestUtil.java +++ b/solr/core/src/java/org/apache/solr/request/json/RequestUtil.java @@ -192,6 +192,7 @@ public class RequestUtil { // implement compat for existing components... JsonQueryConverter jsonQueryConverter = new JsonQueryConverter(); + if (json != null && !isShard) { for (Map.Entry entry : json.entrySet()) { String key = entry.getKey(); @@ -214,48 +215,62 @@ public class RequestUtil { out = "rows"; } else if (SORT.equals(key)) { out = SORT; + } else if ("queries".equals(key)) { + Object queriesJsonObj = entry.getValue(); + if (queriesJsonObj instanceof Map && queriesJsonObj != null) { + @SuppressWarnings("unchecked") + final Map queriesAsMap = (Map) queriesJsonObj; + for (Map.Entry queryJsonProperty : queriesAsMap.entrySet()) { + out = queryJsonProperty.getKey(); + arr = true; + isQuery = true; + convertJsonPropertyToLocalParams(newMap, jsonQueryConverter, queryJsonProperty, out, isQuery, arr); + } + continue; + } else { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, + "Expected Map for 'queries', received " + queriesJsonObj); + } } else if ("params".equals(key) || "facet".equals(key) ) { // handled elsewhere continue; } else { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Unknown top-level key in JSON request : " + key); } - - Object val = entry.getValue(); - - if (arr) { - String[] existing = newMap.get(out); - List lst = val instanceof List ? (List)val : null; - int existingSize = existing==null ? 0 : existing.length; - int jsonSize = lst==null ? 1 : lst.size(); - String[] newval = new String[ existingSize + jsonSize ]; - for (int i=0; i outMap, JsonQueryConverter jsonQueryConverter, Map.Entry jsonProperty, String outKey, boolean isQuery, boolean arr) { + Object val = jsonProperty.getValue(); + + if (arr) { + String[] existing = outMap.get(outKey); + List lst = val instanceof List ? (List)val : null; + int existingSize = existing==null ? 0 : existing.length; + int jsonSize = lst==null ? 1 : lst.size(); + String[] newval = new String[ existingSize + jsonSize ]; + for (int i=0; i map = (Map)o; // To make consistent with json.param handling, we should make query params come after json params (i.e. query params should // appear to overwrite json params. @@ -310,7 +326,7 @@ public class RequestUtil { if (val == null) { params.remove(key); } else if (val instanceof List) { - List lst = (List) val; + List lst = (List) val; String[] vals = new String[lst.size()]; for (int i = 0; i < vals.length; i++) { vals[i] = lst.get(i).toString(); diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java index a0fb090230c..3a6c694098c 100644 --- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java +++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java @@ -56,6 +56,7 @@ public class TestJsonFacets extends SolrTestCaseHS { private static int origTableSize; private static FacetField.FacetMethod origDefaultFacetMethod; + @SuppressWarnings("deprecation") @BeforeClass public static void beforeTests() throws Exception { systemSetPropertySolrDisableShardsWhitelist("true"); @@ -83,6 +84,7 @@ public class TestJsonFacets extends SolrTestCaseHS { } } + @SuppressWarnings("deprecation") @AfterClass public static void afterTests() throws Exception { systemClearPropertySolrDisableShardsWhitelist(); @@ -1063,7 +1065,6 @@ public class TestJsonFacets extends SolrTestCaseHS { } public static void doStatsTemplated(Client client, ModifiableSolrParams p) throws Exception { - int numShards = client.local() ? 1 : client.getClientProvider().all().size(); p.set("Z_num_i", "Z_" + p.get("num_i") ); p.set("Z_num_l", "Z_" + p.get("num_l") ); p.set("sparse_num_d", "sparse_" + p.get("num_d") ); @@ -2290,6 +2291,19 @@ public class TestJsonFacets extends SolrTestCaseHS { "}" ); + //test filter using queries from json.queries + client.testJQ(params(p, "q", "*:*" + , "json.queries", "{catS:{'#cat_sA': '${cat_s}:A'}, ff:[{'#id_1':'-id:1'},{'#id_2':'-id:2'}]}" + , "json.facet", "{" + + ",t_filt1:{${terms} type:terms, field:${cat_s}, domain:{filter:{param:catS} } }" + // test filter via "param" type from .queries + ",t_filt2:{${terms} type:terms, field:${cat_s}, domain:{filter:{param:ff}} }" + // test multi-valued query parameter from .queries + "}" + ) + , "facets=={ count:6, " + + ",t_filt1:{ buckets:[ {val:A, count:2}] } " + + ",t_filt2:{ buckets:[ {val:B, count:2}, {val:A, count:1}] } " + + "}" + ); // test acc reuse (i.e. reset() method). This is normally used for stats that are not calculated in the first phase, // currently non-sorting stats. @@ -2907,7 +2921,7 @@ public class TestJsonFacets extends SolrTestCaseHS { int commitPercent = 10; int ndocs=1000; - Map>> model = new HashMap(); // cat->where->list + Map>> model = new HashMap<>(); // cat->where->list for (int i=0; i