Merged searchrep (5.2.1) to 5.2.N (5.2.1)

136673 msuzuki: SEARCH-340, adding facet range search


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@137038 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gethin James
2017-06-01 11:07:54 +00:00
parent 6981d5bf57
commit be9d0cc1f7
7 changed files with 121 additions and 17 deletions

View File

@@ -29,7 +29,6 @@ package org.alfresco.rest.api.search.impl;
import static org.alfresco.rest.api.search.impl.StoreMapper.DELETED; import static org.alfresco.rest.api.search.impl.StoreMapper.DELETED;
import static org.alfresco.rest.api.search.impl.StoreMapper.LIVE_NODES; import static org.alfresco.rest.api.search.impl.StoreMapper.LIVE_NODES;
import static org.alfresco.rest.api.search.impl.StoreMapper.VERSIONS; import static org.alfresco.rest.api.search.impl.StoreMapper.VERSIONS;
import com.sun.javafx.font.Metrics;
import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet; import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericBucket; import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericBucket;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericFacetResponse; import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericFacetResponse;
@@ -322,6 +321,9 @@ public class ResultMapper
Map<String, List<Pair<String, Integer>>> facetInterval = solrResultSet.getFacetIntervals(); Map<String, List<Pair<String, Integer>>> facetInterval = solrResultSet.getFacetIntervals();
facets.addAll(getGenericFacetsForIntervals(facetInterval, searchQuery)); facets.addAll(getGenericFacetsForIntervals(facetInterval, searchQuery));
Map<String, List<Pair<String, Integer>>> facetRanges = solrResultSet.getFacetRanges();
facets.addAll(getGenericFacetsForRanges(facetRanges, searchQuery));
List<GenericFacetResponse> stats = getFieldStats(searchRequestContext, solrResultSet.getStats()); List<GenericFacetResponse> stats = getFieldStats(searchRequestContext, solrResultSet.getStats());
List<GenericFacetResponse> pimped = getPivots(searchRequestContext, solrResultSet.getPivotFacets(), stats); List<GenericFacetResponse> pimped = getPivots(searchRequestContext, solrResultSet.getPivotFacets(), stats);
@@ -473,7 +475,32 @@ public class ResultMapper
} }
return Collections.emptyList(); return Collections.emptyList();
} }
/**
* Transforms the facet range response into generic facet response.
* @param facetFields
* @param searchQuery
* @return GenericFacetResponse
*/
protected static List<GenericFacetResponse> getGenericFacetsForRanges(Map<String, List<Pair<String, Integer>>> facetFields, SearchQuery searchQuery)
{
List<GenericFacetResponse> ffcs = new ArrayList<>(facetFields.size());
if (facetFields != null && !facetFields.isEmpty())
{
for (Entry<String, List<Pair<String, Integer>>> facet:facetFields.entrySet())
{
if (facet.getValue() != null && !facet.getValue().isEmpty())
{
List<GenericBucket> buckets = new ArrayList<>();
facet.getValue().forEach(action -> buckets.add(
new GenericBucket(action.getFirst(), null, null ,
new HashSet<Metric>(Arrays.asList(new SimpleMetric(METRIC_TYPE.count,String.valueOf(action.getSecond())))),
null)));
ffcs.add(new GenericFacetResponse(FACET_TYPE.range, facet.getKey(), buckets));
}
}
}
return ffcs;
}
/** /**
* Returns generic faceting responses for Intervals * Returns generic faceting responses for Intervals
* @param facetFields * @param facetFields

View File

@@ -51,6 +51,7 @@ import org.alfresco.service.cmr.search.Interval;
import org.alfresco.service.cmr.search.IntervalParameters; import org.alfresco.service.cmr.search.IntervalParameters;
import org.alfresco.service.cmr.search.IntervalSet; import org.alfresco.service.cmr.search.IntervalSet;
import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.RangeParameters;
import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchParameters.FieldFacet; import org.alfresco.service.cmr.search.SearchParameters.FieldFacet;
import org.alfresco.service.cmr.search.SearchParameters.FieldFacetMethod; import org.alfresco.service.cmr.search.SearchParameters.FieldFacetMethod;
@@ -510,7 +511,24 @@ public class SearchMapper
} }
sp.setInterval(facetIntervals); sp.setInterval(facetIntervals);
} }
/**
* Sets the Range Parameters object on search parameters
* @param sp SearchParameters
* @param rangeParams RangeParameters
*/
public void fromFacetRange(SearchParameters sp, RangeParameters rangeParams)
{
if(rangeParams != null)
{
ParameterCheck.mandatory("facetRange", rangeParams);
ParameterCheck.mandatory("field ", rangeParams.getField());
ParameterCheck.mandatory("facet range start ", rangeParams.getStart());
ParameterCheck.mandatory("facet range end ", rangeParams.getEnd());
ParameterCheck.mandatory("facet range gap ", rangeParams.getGap());
sp.setRange(rangeParams);
}
}
public void fromPivot(SearchParameters sp, List<StatsRequestParameters> stats, FacetFields facetFields, List<Pivot> pivots, SearchRequestContext searchRequestContext) public void fromPivot(SearchParameters sp, List<StatsRequestParameters> stats, FacetFields facetFields, List<Pivot> pivots, SearchRequestContext searchRequestContext)
{ {
if (facetFields != null && pivots != null && !pivots.isEmpty()) if (facetFields != null && pivots != null && !pivots.isEmpty())

View File

@@ -29,6 +29,7 @@ package org.alfresco.rest.api.search.model;
import org.alfresco.rest.framework.resource.parameters.Paging; import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.cmr.search.GeneralHighlightParameters; import org.alfresco.service.cmr.search.GeneralHighlightParameters;
import org.alfresco.service.cmr.search.IntervalParameters; import org.alfresco.service.cmr.search.IntervalParameters;
import org.alfresco.service.cmr.search.RangeParameters;
import org.alfresco.service.cmr.search.StatsRequestParameters; import org.alfresco.service.cmr.search.StatsRequestParameters;
import org.codehaus.jackson.annotate.JsonCreator; import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonProperty;
@@ -60,9 +61,10 @@ public class SearchQuery
private final boolean includeRequest; private final boolean includeRequest;
private final List<Pivot> pivots; private final List<Pivot> pivots;
private final List<StatsRequestParameters> stats; private final List<StatsRequestParameters> stats;
private final RangeParameters facetRange;
public static final SearchQuery EMPTY = new SearchQuery(null, null, null, null, null, null, public static final SearchQuery EMPTY = new SearchQuery(null, null, null, null, null, null,
null,null, null, null, null,null, null, null, null, null, null, null); null,null, null, null, null,null, null, null, null, null, null, null,null);
@JsonCreator @JsonCreator
public SearchQuery(@JsonProperty("query") Query query, public SearchQuery(@JsonProperty("query") Query query,
@@ -82,7 +84,8 @@ public class SearchQuery
@JsonProperty("highlight")GeneralHighlightParameters highlight, @JsonProperty("highlight")GeneralHighlightParameters highlight,
@JsonProperty("facetIntervals")IntervalParameters facetIntervals, @JsonProperty("facetIntervals")IntervalParameters facetIntervals,
@JsonProperty("pivots") List<Pivot> pivots, @JsonProperty("pivots") List<Pivot> pivots,
@JsonProperty("stats") List<StatsRequestParameters> stats) @JsonProperty("stats") List<StatsRequestParameters> stats,
@JsonProperty("facetRange") RangeParameters facetRange)
{ {
this.query = query; this.query = query;
this.includeRequest = includeRequest==null?false:includeRequest; this.includeRequest = includeRequest==null?false:includeRequest;
@@ -102,6 +105,7 @@ public class SearchQuery
this.facetIntervals = facetIntervals; this.facetIntervals = facetIntervals;
this.pivots = pivots; this.pivots = pivots;
this.stats = stats; this.stats = stats;
this.facetRange = facetRange;
} }
public Query getQuery() public Query getQuery()
@@ -192,4 +196,10 @@ public class SearchQuery
{ {
return stats; return stats;
} }
public RangeParameters getFacetRange()
{
return facetRange;
}
} }

View File

@@ -117,7 +117,7 @@ public class ResultMapperTests
+ "\"facet_counts\":{\"facet_queries\":{\"small\":0,\"large\":0,\"xtra small\":3,\"xtra large\":0,\"medium\":8,\"XX large\":0}," + "\"facet_counts\":{\"facet_queries\":{\"small\":0,\"large\":0,\"xtra small\":3,\"xtra large\":0,\"medium\":8,\"XX large\":0},"
+ "\"facet_fields\":{\"content.size\":[\"Big\",8,\"Brown\",3,\"Fox\",5,\"Jumped\",2,\"somewhere\",3]}," + "\"facet_fields\":{\"content.size\":[\"Big\",8,\"Brown\",3,\"Fox\",5,\"Jumped\",2,\"somewhere\",3]},"
+"\"facet_dates\":{}," +"\"facet_dates\":{},"
+"\"facet_ranges\":{}," +"\"facet_ranges\":{\"content.size\": {\"counts\": [\"0\",4,\"100\",6,\"200\",3],\"gap\": 100,\"start\": 0,\"end\": 300}},"
+"\"facet_pivot\":{\"creator,modifier\":[{\"field\":\"creator\",\"count\":7,\"pivot\":[{\"field\":\"modifier\",\"count\":3,\"value\":\"mjackson\"},{\"field\":\"modifier\",\"count\":4,\"value\":\"admin\"}],\"value\":\"mjackson\"}]}," +"\"facet_pivot\":{\"creator,modifier\":[{\"field\":\"creator\",\"count\":7,\"pivot\":[{\"field\":\"modifier\",\"count\":3,\"value\":\"mjackson\"},{\"field\":\"modifier\",\"count\":4,\"value\":\"admin\"}],\"value\":\"mjackson\"}]},"
+"\"facet_intervals\":{\"creator\":{\"last\":4,\"first\":0},\"TheCreated\":{\"earlier\":5,\"lastYear\":0,\"currentYear\":854}}" +"\"facet_intervals\":{\"creator\":{\"last\":4,\"first\":0},\"TheCreated\":{\"earlier\":5,\"lastYear\":0,\"currentYear\":854}}"
+ "}," + "},"
@@ -320,8 +320,8 @@ public class ResultMapperTests
assertEquals("great", searchContext.getRequest().getQuery().getUserQuery()); assertEquals("great", searchContext.getRequest().getQuery().getUserQuery());
//Pivot //Pivot
assertEquals(5, searchContext.getFacets().size()); assertEquals(6, searchContext.getFacets().size());
GenericFacetResponse pivotFacet = searchContext.getFacets().get(2); GenericFacetResponse pivotFacet = searchContext.getFacets().get(3);
assertEquals(FACET_TYPE.pivot,pivotFacet.getType()); assertEquals(FACET_TYPE.pivot,pivotFacet.getType());
assertEquals("creator",pivotFacet.getLabel()); assertEquals("creator",pivotFacet.getLabel());
assertEquals(2, pivotFacet.getBuckets().size()); assertEquals(2, pivotFacet.getBuckets().size());
@@ -348,7 +348,7 @@ public class ResultMapperTests
assertEquals("{count=4}",metrics[0].getValue().toString()); assertEquals("{count=4}",metrics[0].getValue().toString());
//Stats //Stats
GenericFacetResponse statsFacet = searchContext.getFacets().get(3); GenericFacetResponse statsFacet = searchContext.getFacets().get(4);
assertEquals(FACET_TYPE.stats,statsFacet.getType()); assertEquals(FACET_TYPE.stats,statsFacet.getType());
assertEquals("created",statsFacet.getLabel()); assertEquals("created",statsFacet.getLabel());
Set<Metric> statsMetrics = statsFacet.getBuckets().get(0).getMetrics(); Set<Metric> statsMetrics = statsFacet.getBuckets().get(0).getMetrics();
@@ -362,7 +362,7 @@ public class ResultMapperTests
assertTrue(statsMetrics.contains(new SimpleMetric(METRIC_TYPE.sum, 1.458318720769983E15))); assertTrue(statsMetrics.contains(new SimpleMetric(METRIC_TYPE.sum, 1.458318720769983E15)));
assertTrue(statsMetrics.contains(new SimpleMetric(METRIC_TYPE.stddev, 5.6250677994522545E10))); assertTrue(statsMetrics.contains(new SimpleMetric(METRIC_TYPE.stddev, 5.6250677994522545E10)));
statsFacet = searchContext.getFacets().get(4); statsFacet = searchContext.getFacets().get(5);
assertEquals("numericLabel",statsFacet.getLabel()); assertEquals("numericLabel",statsFacet.getLabel());
statsMetrics = statsFacet.getBuckets().get(0).getMetrics(); statsMetrics = statsFacet.getBuckets().get(0).getMetrics();
assertEquals(7,statsMetrics.size()); assertEquals(7,statsMetrics.size());
@@ -459,6 +459,33 @@ public class ResultMapperTests
assertEquals(METRIC_TYPE.count,((SimpleMetric) metrics[0]).getType()); assertEquals(METRIC_TYPE.count,((SimpleMetric) metrics[0]).getType());
assertEquals("854",((SimpleMetric) metrics[0]).getValue().get("count")); assertEquals("854",((SimpleMetric) metrics[0]).getValue().get("count"));
} }
@Test
public void testRange() throws Exception
{
ResultSet results = mockResultset(Collections.emptyList(),Collections.emptyList());
SearchQuery searchQuery = helper.searchQueryFromJson();
SearchRequestContext searchRequest = SearchRequestContext.from(searchQuery);
SearchParameters searchParams = searchMapper.toSearchParameters(EMPTY_PARAMS, searchQuery, searchRequest);
SearchContext searchContext = mapper.toSearchContext((SolrJSONResultSet) results, searchRequest, searchQuery, 0);
//Numeric facet range
List<GenericFacetResponse> rangeFacets = searchContext.getFacets().stream()
.filter(f -> f.getType().equals(FACET_TYPE.range)).collect(Collectors.toList());
assertEquals(1, rangeFacets.size());
assertEquals(3, rangeFacets.get(0).getBuckets().size());
assertEquals("content.size",rangeFacets.get(0).getLabel());
assertEquals("0",rangeFacets.get(0).getBuckets().get(0).getLabel());
Object[] metrics = rangeFacets.get(0).getBuckets().get(0).getMetrics().toArray();
assertEquals("4",((SimpleMetric) metrics[0]).getValue().get("count"));
assertEquals("100",rangeFacets.get(0).getBuckets().get(1).getLabel());
metrics = rangeFacets.get(0).getBuckets().get(1).getMetrics().toArray();
assertEquals("6",((SimpleMetric) metrics[0]).getValue().get("count"));
assertEquals("200",rangeFacets.get(0).getBuckets().get(2).getLabel());
metrics = rangeFacets.get(0).getBuckets().get(2).getMetrics().toArray();
assertEquals("3",((SimpleMetric) metrics[0]).getValue().get("count"));
}
@Test @Test
/** /**

View File

@@ -59,6 +59,7 @@ import org.alfresco.service.cmr.search.Interval;
import org.alfresco.service.cmr.search.IntervalParameters; import org.alfresco.service.cmr.search.IntervalParameters;
import org.alfresco.service.cmr.search.IntervalSet; import org.alfresco.service.cmr.search.IntervalSet;
import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.RangeParameters;
import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchParameters.FieldFacet; import org.alfresco.service.cmr.search.SearchParameters.FieldFacet;
import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.search.SearchService;
@@ -797,16 +798,31 @@ public class SearchMapperTests
searchMapper.fromFacetIntervals(searchParameters, intervalParameters); searchMapper.fromFacetIntervals(searchParameters, intervalParameters);
assertEquals(searchParameters.getInterval(), intervalParameters); assertEquals(searchParameters.getInterval(), intervalParameters);
} }
@Test
public void facetRange()
{
SearchParameters searchParameters = new SearchParameters();
RangeParameters rangeParams = new RangeParameters(null, null, null, null);
try
{
searchMapper.fromFacetRange(searchParameters, rangeParams);
fail();
}
catch (IllegalArgumentException iae)
{
assertNotNull(iae);
}
rangeParams = new RangeParameters("content.size", "0", "100000", "1000");
searchMapper.fromFacetRange(searchParameters, rangeParams);
assertEquals(searchParameters.getRange(), rangeParams);
}
private SearchQuery minimalQuery() private SearchQuery minimalQuery()
{ {
Query query = new Query("cmis", "foo", ""); Query query = new Query("cmis", "foo", "");
SearchQuery sq = new SearchQuery(query, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); SearchQuery sq = new SearchQuery(query, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,null);
return sq; return sq;
} }
@Test
public void facetGroup()
{
}
} }

View File

@@ -45,6 +45,7 @@ import org.alfresco.service.cmr.search.FieldHighlightParameters;
import org.alfresco.service.cmr.search.Interval; import org.alfresco.service.cmr.search.Interval;
import org.alfresco.service.cmr.search.IntervalParameters; import org.alfresco.service.cmr.search.IntervalParameters;
import org.alfresco.service.cmr.search.IntervalSet; import org.alfresco.service.cmr.search.IntervalSet;
import org.alfresco.service.cmr.search.RangeParameters;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@@ -170,6 +171,10 @@ public class SearchQuerySerializerTests
assertEquals(1,searchQuery.getStats().size()); assertEquals(1,searchQuery.getStats().size());
assertEquals("cm:creator",searchQuery.getStats().get(0).getField()); assertEquals("cm:creator",searchQuery.getStats().get(0).getField());
assertEquals("mylabel",searchQuery.getStats().get(0).getLabel()); assertEquals("mylabel",searchQuery.getStats().get(0).getLabel());
//Range Facet
RangeParameters range = searchQuery.getFacetRange();
assertNotNull(range);
} }
@Test @Test

View File

@@ -64,6 +64,7 @@ public class SerializerTestHelper implements RequestReader
+ "\"facetFields\": {\"facets\": [{\"field\": \"cm:creator\",\"prefix\": \"myquery2\",\"sort\": \"COUNT\",\"missing\": \"false\"}, {\"field\": \"modifier\",\"label\": \"mylabel\",\"method\": \"FC\",\"mincount\": \"5\"}, {\"field\": \"owner\",\"label\": \"ownerLabel\"}]}," + "\"facetFields\": {\"facets\": [{\"field\": \"cm:creator\",\"prefix\": \"myquery2\",\"sort\": \"COUNT\",\"missing\": \"false\"}, {\"field\": \"modifier\",\"label\": \"mylabel\",\"method\": \"FC\",\"mincount\": \"5\"}, {\"field\": \"owner\",\"label\": \"ownerLabel\"}]},"
+ "\"facetQueries\": [{\"query\": \"cm:created:bob\",\"label\": \"small\"}]," + "\"facetQueries\": [{\"query\": \"cm:created:bob\",\"label\": \"small\"}],"
+ "\"pivots\": [{\"key\": \"mylabel\"}]," + "\"pivots\": [{\"key\": \"mylabel\"}],"
+ "\"facetRange\": {\"field\": \"content.size\",\"facet.range.start\": \"0\",\"facet.range.end\": \"300\",\"facet.range.gap\": \"100\"},"
+ "\"facetIntervals\": {\"sets\": [{ \"label\": \"king\", \"start\": \"1\", \"end\": \"2\",\"startInclusive\": true,\"endInclusive\": false}]" + "\"facetIntervals\": {\"sets\": [{ \"label\": \"king\", \"start\": \"1\", \"end\": \"2\",\"startInclusive\": true,\"endInclusive\": false}]"
+ ",\"intervals\": [{\"field\": \"cm:creator\",\"label\": \"creator\"," + ",\"intervals\": [{\"field\": \"cm:creator\",\"label\": \"creator\","
+ "\"sets\": [{\"label\": \"last\",\"start\": \"a\",\"end\": \"b\",\"startInclusive\": false}]" + "\"sets\": [{\"label\": \"last\",\"start\": \"a\",\"end\": \"b\",\"startInclusive\": false}]"