SOLR-13417: handle stats on date/str fields in solrj's JSON facet resp

* Except for min/max aggregation in all other cases values woudl be
  number. As for same data/string field, value can vary based on
  aggregation used, capture response in Map<String, Object>
This commit is contained in:
Munendra S N 2019-09-28 11:51:34 +05:30
parent 7752964e19
commit e5d95011f0
5 changed files with 38 additions and 22 deletions

View File

@ -243,6 +243,9 @@ Bug Fixes
* SOLR-13180: Fix ClassCastException in Json Request API (Johannes Kloos, Jan Høydahl, Munendra S N)
* SOLR-13417: Handle stats aggregation on date and string fields in SolrJ's JSON facet response processing
(Jason Gerlowski, Munendra S N)
Other Changes
----------------------

View File

@ -17,6 +17,7 @@
package org.apache.solr.client.solrj.response.json;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -35,14 +36,14 @@ public class NestableJsonFacet {
private long domainCount;
private final Map<String, NestableJsonFacet> queryFacetsByName;
private final Map<String, BucketBasedJsonFacet> bucketBasedFacetByName;
private final Map<String, Number> statFacetsByName;
private final Map<String, Object> statsByName;
private final Map<String, HeatmapJsonFacet> heatmapFacetsByName;
public NestableJsonFacet(NamedList<Object> facetNL) {
queryFacetsByName = new HashMap<>();
bucketBasedFacetByName = new HashMap<>();
statFacetsByName = new HashMap<>();
heatmapFacetsByName = new HashMap<>();
statsByName = new HashMap<>();
for (Map.Entry<String, Object> entry : facetNL) {
final String key = entry.getKey();
@ -50,8 +51,10 @@ public class NestableJsonFacet {
continue;
} else if ("count".equals(key)) {
domainCount = ((Number) entry.getValue()).longValue();
} else if(entry.getValue() instanceof Number) { // Stat/agg facet value
statFacetsByName.put(key, (Number)entry.getValue());
} else if (entry.getValue() instanceof Number || entry.getValue() instanceof String ||
entry.getValue() instanceof Date) {
// Stat/agg facet value
statsByName.put(key, entry.getValue());
} else if(entry.getValue() instanceof NamedList) { // Either heatmap/query/range/terms facet
final NamedList<Object> facet = (NamedList<Object>) entry.getValue();
final boolean isBucketBased = facet.get("buckets") != null;
@ -103,17 +106,17 @@ public class NestableJsonFacet {
}
/**
* Retrieve the value for a stat or agg facet with the provided name
* Retrieve the value for a stat or agg with the provided name
*/
public Number getStatFacetValue(String name) {
return statFacetsByName.get(name);
public Object getStatValue(String name) {
return statsByName.get(name);
}
/**
* @return the names of any stat or agg facets that are direct descendants of this facet
* @return the names of any stat or agg that are direct descendants of this facet
*/
public Set<String> getStatFacetNames() {
return statFacetsByName.keySet();
public Set<String> getStatNames() {
return statsByName.keySet();
}
/**

View File

@ -20,6 +20,7 @@ package org.apache.solr.client.ref_guide_examples;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -34,10 +35,10 @@ import org.apache.solr.client.solrj.request.json.JsonQueryRequest;
import org.apache.solr.client.solrj.request.json.QueryFacetMap;
import org.apache.solr.client.solrj.request.json.RangeFacetMap;
import org.apache.solr.client.solrj.request.json.TermsFacetMap;
import org.apache.solr.client.solrj.response.json.BucketJsonFacet;
import org.apache.solr.client.solrj.response.json.NestableJsonFacet;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.client.solrj.response.json.BucketJsonFacet;
import org.apache.solr.client.solrj.response.json.NestableJsonFacet;
import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
@ -455,6 +456,7 @@ public class JsonRequestApiTest extends SolrCloudTestCase {
.setQuery("memory")
.withFilter("inStock:true")
.withStatFacet("avg_price", "avg(price)")
.withStatFacet("min_manufacturedate_dt", "min(manufacturedate_dt)")
.withStatFacet("num_suppliers", "unique(manu_exact)")
.withStatFacet("median_weight", "percentile(weight,50)");
QueryResponse queryResponse = request.process(solrClient, COLLECTION_NAME);
@ -464,9 +466,13 @@ public class JsonRequestApiTest extends SolrCloudTestCase {
assertEquals(4, queryResponse.getResults().getNumFound());
assertEquals(4, queryResponse.getResults().size());
final NestableJsonFacet topLevelFacetingData = queryResponse.getJsonFacetingResponse();
assertEquals(146.66, (double) topLevelFacetingData.getStatFacetValue("avg_price"), 0.5);
assertEquals(3, topLevelFacetingData.getStatFacetValue("num_suppliers"));
assertEquals(352.0, (double) topLevelFacetingData.getStatFacetValue("median_weight"), 0.5);
assertEquals(146.66, (double) topLevelFacetingData.getStatValue("avg_price"), 0.5);
assertEquals(3, topLevelFacetingData.getStatValue("num_suppliers"));
assertEquals(352.0, (double) topLevelFacetingData.getStatValue("median_weight"), 0.5);
Object val = topLevelFacetingData.getStatValue("min_manufacturedate_dt");
assertTrue(val instanceof Date);
assertEquals("2006-02-13T15:26:37Z", ((Date)val).toInstant().toString());
}
@Test
@ -478,6 +484,7 @@ public class JsonRequestApiTest extends SolrCloudTestCase {
.setQuery("*:*")
.withFilter("price:[1.0 TO *]")
.withFilter("popularity:[0 TO 10]")
.withStatFacet("min_manu_id_s", "min(manu_id_s)")
.withStatFacet("avg_value", "avg(div(popularity,price))");
QueryResponse queryResponse = request.process(solrClient, COLLECTION_NAME);
//end::solrj-json-metrics-facet-simple[]
@ -486,7 +493,10 @@ public class JsonRequestApiTest extends SolrCloudTestCase {
assertEquals(13, queryResponse.getResults().getNumFound());
assertEquals(10, queryResponse.getResults().size());
final NestableJsonFacet topLevelFacetingData = queryResponse.getJsonFacetingResponse();
assertEquals(0.036, (double) topLevelFacetingData.getStatFacetValue("avg_value"), 0.1);
assertEquals(0.036, (double) topLevelFacetingData.getStatValue("avg_value"), 0.1);
Object val = topLevelFacetingData.getStatValue("min_manu_id_s");
assertTrue(val instanceof String);
assertEquals("apple", val.toString());
}
@Test
@ -511,7 +521,7 @@ public class JsonRequestApiTest extends SolrCloudTestCase {
assertEquals(13, queryResponse.getResults().getNumFound());
assertEquals(10, queryResponse.getResults().size());
final NestableJsonFacet topLevelFacetingData = queryResponse.getJsonFacetingResponse();
assertEquals(0.108, (double) topLevelFacetingData.getStatFacetValue("avg_value"), 0.1);
assertEquals(0.108, (double) topLevelFacetingData.getStatValue("avg_value"), 0.1);
}
@Test
@ -551,7 +561,7 @@ public class JsonRequestApiTest extends SolrCloudTestCase {
assertEquals(10, queryResponse.getResults().size());
final NestableJsonFacet topLevelFacetingData = queryResponse.getJsonFacetingResponse();
assertEquals(2, topLevelFacetingData.getQueryFacet("high_popularity").getCount());
assertEquals(199.5, topLevelFacetingData.getQueryFacet("high_popularity").getStatFacetValue("average_price"));
assertEquals(199.5, topLevelFacetingData.getQueryFacet("high_popularity").getStatValue("average_price"));
}
@Test

View File

@ -545,8 +545,8 @@ public class DirectJsonQueryRequestFacetingIntegrationTest extends SolrCloudTest
private void assertHasStatFacetWithValue(NestableJsonFacet response, String expectedFacetName, Double expectedStatValue) {
assertTrue("Expected response to have stat facet named '" + expectedFacetName + "'",
response.getStatFacetValue(expectedFacetName) != null);
assertEquals(expectedStatValue, response.getStatFacetValue(expectedFacetName));
response.getStatValue(expectedFacetName) != null);
assertEquals(expectedStatValue, response.getStatValue(expectedFacetName));
}
private void assertExpectedDocumentsFoundAndReturned(QueryResponse response, int expectedNumFound, int expectedReturned) {

View File

@ -571,8 +571,8 @@ public class JsonQueryRequestFacetingIntegrationTest extends SolrCloudTestCase {
private void assertHasStatFacetWithValue(NestableJsonFacet response, String expectedFacetName, Double expectedStatValue) {
assertTrue("Expected response to have stat facet named '" + expectedFacetName + "'",
response.getStatFacetValue(expectedFacetName) != null);
assertEquals(expectedStatValue, response.getStatFacetValue(expectedFacetName));
response.getStatValue(expectedFacetName) != null);
assertEquals(expectedStatValue, response.getStatValue(expectedFacetName));
}
private void assertExpectedDocumentsFoundAndReturned(QueryResponse response, int expectedNumFound, int expectedReturned) {