mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged searchbcr (5.2.1) to 5.2.N (5.2.1)
135953 msuzuki: SEARCH-374, added new response to display group faceting in buckets git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@136097 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -29,6 +29,16 @@ 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 java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet;
|
import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet;
|
||||||
import org.alfresco.repo.version.Version2Model;
|
import org.alfresco.repo.version.Version2Model;
|
||||||
import org.alfresco.rest.api.DeletedNodes;
|
import org.alfresco.rest.api.DeletedNodes;
|
||||||
@@ -64,13 +74,7 @@ import org.alfresco.util.Pair;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import com.google.gdata.data.introspection.Collection;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps from a ResultSet to a json public api representation.
|
* Maps from a ResultSet to a json public api representation.
|
||||||
@@ -131,7 +135,7 @@ public class ResultMapper
|
|||||||
{
|
{
|
||||||
SearchContext context = null;
|
SearchContext context = null;
|
||||||
Integer total = null;
|
Integer total = null;
|
||||||
List<Node> noderesults = new ArrayList();
|
List<Node> noderesults = new ArrayList<Node>();
|
||||||
Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
|
Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
|
||||||
Map<NodeRef, List<Pair<String, List<String>>>> hightLighting = results.getHighlighting();
|
Map<NodeRef, List<Pair<String, List<String>>>> hightLighting = results.getHighlighting();
|
||||||
int notFound = 0;
|
int notFound = 0;
|
||||||
@@ -272,11 +276,21 @@ public class ResultMapper
|
|||||||
Map<String, Integer> facetQueries = solrResultSet.getFacetQueries();
|
Map<String, Integer> facetQueries = solrResultSet.getFacetQueries();
|
||||||
List<FacetQueryContext> facetResults = null;
|
List<FacetQueryContext> facetResults = null;
|
||||||
SpellCheckContext spellCheckContext = null;
|
SpellCheckContext spellCheckContext = null;
|
||||||
List<FacetFieldContext> ffcs = null;
|
List<FacetFieldContext> ffcs = new ArrayList<FacetFieldContext>();
|
||||||
|
|
||||||
//Facet queries
|
//Facet queries
|
||||||
if(facetQueries!= null && !facetQueries.isEmpty())
|
if(facetQueries!= null && !facetQueries.isEmpty())
|
||||||
{
|
{
|
||||||
|
//If group by field populated in query facet return bucketing into facet field.
|
||||||
|
List<FacetFieldContext> facetQueryForFields =
|
||||||
|
getFacetBucketsFromFacetQueries(facetQueries,searchQuery);
|
||||||
|
if(!facetQueryForFields.isEmpty())
|
||||||
|
{
|
||||||
|
ffcs.addAll(facetQueryForFields);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Return the old way facet query with no bucketing.
|
||||||
facetResults = new ArrayList<>(facetQueries.size());
|
facetResults = new ArrayList<>(facetQueries.size());
|
||||||
for (Entry<String, Integer> fq:facetQueries.entrySet())
|
for (Entry<String, Integer> fq:facetQueries.entrySet())
|
||||||
{
|
{
|
||||||
@@ -289,10 +303,11 @@ public class ResultMapper
|
|||||||
facetResults.add(new FacetQueryContext(fq.getKey(), filterQuery, fq.getValue()));
|
facetResults.add(new FacetQueryContext(fq.getKey(), filterQuery, fq.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Field Facets
|
//Field Facets
|
||||||
Map<String, List<Pair<String, Integer>>> facetFields = solrResultSet.getFieldFacets();
|
Map<String, List<Pair<String, Integer>>> facetFields = solrResultSet.getFieldFacets();
|
||||||
ffcs = getFacetBucketsForFacetFields(facetFields, searchQuery);
|
ffcs.addAll(getFacetBucketsForFacetFields(facetFields, searchQuery));
|
||||||
|
|
||||||
Map<String, List<Pair<String, Integer>>> facetInterval = solrResultSet.getFacetIntervals();
|
Map<String, List<Pair<String, Integer>>> facetInterval = solrResultSet.getFacetIntervals();
|
||||||
List<FacetFieldContext> intervals = getFacetBucketsForIntervals(facetInterval, searchQuery);
|
List<FacetFieldContext> intervals = getFacetBucketsForIntervals(facetInterval, searchQuery);
|
||||||
@@ -308,7 +323,49 @@ public class ResultMapper
|
|||||||
context = new SearchContext(solrResultSet.getLastIndexedTxId(), facetResults, ffcs, intervals, spellCheckContext, searchQuery.includeRequest()?searchQuery:null);
|
context = new SearchContext(solrResultSet.getLastIndexedTxId(), facetResults, ffcs, intervals, spellCheckContext, searchQuery.includeRequest()?searchQuery:null);
|
||||||
return isNullContext(context)?null:context;
|
return isNullContext(context)?null:context;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Builds a facet field from facet queries.
|
||||||
|
* @param facetQueries
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected List<FacetFieldContext> getFacetBucketsFromFacetQueries(Map<String, Integer> facetQueries, SearchQuery searchQuery)
|
||||||
|
{
|
||||||
|
List<FacetFieldContext> facetResults = new ArrayList<FacetFieldContext>();
|
||||||
|
Map<String,List<Bucket>> groups = new HashMap<>();
|
||||||
|
String group = null;
|
||||||
|
|
||||||
|
for (Entry<String, Integer> fq:facetQueries.entrySet())
|
||||||
|
{
|
||||||
|
String filterQuery = null;
|
||||||
|
if (searchQuery != null && searchQuery.getFacetQueries() != null)
|
||||||
|
{
|
||||||
|
Optional<FacetQuery> found = searchQuery.getFacetQueries().stream().filter(facetQuery -> fq.getKey().equals(facetQuery.getLabel())).findFirst();
|
||||||
|
filterQuery = found.isPresent()? found.get().getQuery():fq.getKey();
|
||||||
|
if(found.isPresent() && found.get().getGroup() != null)
|
||||||
|
{
|
||||||
|
group= found.get().getGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(group != null && !group.isEmpty())
|
||||||
|
{
|
||||||
|
if(groups.containsKey(group))
|
||||||
|
{
|
||||||
|
groups.get(group).add(new Bucket(fq.getKey(), filterQuery, fq.getValue(), null));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<Bucket> l = new ArrayList<Bucket>();
|
||||||
|
l.add(new Bucket(fq.getKey(),filterQuery, fq.getValue(),null));
|
||||||
|
groups.put(group, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!groups.isEmpty())
|
||||||
|
{
|
||||||
|
groups.forEach((a,v) -> facetResults.add(new FacetFieldContext(a,v)));
|
||||||
|
}
|
||||||
|
return facetResults;
|
||||||
|
}
|
||||||
protected List<FacetFieldContext> getFacetBucketsForFacetFields(Map<String, List<Pair<String, Integer>>> facetFields, SearchQuery searchQuery)
|
protected List<FacetFieldContext> getFacetBucketsForFacetFields(Map<String, List<Pair<String, Integer>>> facetFields, SearchQuery searchQuery)
|
||||||
{
|
{
|
||||||
if (facetFields != null && !facetFields.isEmpty())
|
if (facetFields != null && !facetFields.isEmpty())
|
||||||
@@ -348,7 +405,7 @@ public class ResultMapper
|
|||||||
|
|
||||||
return ffcs;
|
return ffcs;
|
||||||
}
|
}
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<FacetFieldContext> getFacetBucketsForIntervals(Map<String, List<Pair<String, Integer>>> facetFields, SearchQuery searchQuery)
|
protected List<FacetFieldContext> getFacetBucketsForIntervals(Map<String, List<Pair<String, Integer>>> facetFields, SearchQuery searchQuery)
|
||||||
|
@@ -35,12 +35,16 @@ public class FacetQuery
|
|||||||
{
|
{
|
||||||
private final String query;
|
private final String query;
|
||||||
private final String label;
|
private final String label;
|
||||||
|
private final String group;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public FacetQuery(@JsonProperty("query") String query, @JsonProperty("label") String label)
|
public FacetQuery(@JsonProperty("query") String query,
|
||||||
|
@JsonProperty("label") String label,
|
||||||
|
@JsonProperty("group") String group)
|
||||||
{
|
{
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
this.group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getQuery()
|
public String getQuery()
|
||||||
@@ -52,4 +56,8 @@ public class FacetQuery
|
|||||||
{
|
{
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
public String getGroup()
|
||||||
|
{
|
||||||
|
return group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -270,7 +270,6 @@ public class ResultMapperTests
|
|||||||
assertEquals("alfresco",searchContext.getSpellCheck().getSuggestions().get(0));
|
assertEquals("alfresco",searchContext.getSpellCheck().getSuggestions().get(0));
|
||||||
assertEquals(1, searchContext.getFacetsFields().size());
|
assertEquals(1, searchContext.getFacetsFields().size());
|
||||||
assertEquals("content.size",searchContext.getFacetsFields().get(0).getLabel());
|
assertEquals("content.size",searchContext.getFacetsFields().get(0).getLabel());
|
||||||
assertEquals(5,searchContext.getFacetsFields().get(0).getBuckets().size());
|
|
||||||
|
|
||||||
//Facet intervals
|
//Facet intervals
|
||||||
assertEquals(2, searchContext.getFacetIntervals().size());
|
assertEquals(2, searchContext.getFacetIntervals().size());
|
||||||
@@ -320,6 +319,51 @@ public class ResultMapperTests
|
|||||||
assertEquals(")",sp.getHighlight().getFields().get(1).getPostfix());
|
assertEquals(")",sp.getHighlight().getFields().get(1).getPostfix());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test facet group with out facet fields
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testFacetingGroupResponse() throws Exception
|
||||||
|
{
|
||||||
|
String jsonQuery = "{\"query\": {\"query\": \"alfresco\"},"
|
||||||
|
+ "\"facetQueries\": ["
|
||||||
|
+ "{\"query\": \"content.size:[o TO 102400]\", \"label\": \"small\",\"group\":\"foo\"},"
|
||||||
|
+ "{\"query\": \"content.size:[102400 TO 1048576]\", \"label\": \"medium\",\"group\":\"foo\"},"
|
||||||
|
+ "{\"query\": \"content.size:[1048576 TO 16777216]\", \"label\": \"large\",\"group\":\"foo\"}]"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
String expectedResponse = "{\"responseHeader\":{\"status\":0,\"QTime\":9},\"_original_parameters_\":\"org.apache.solr.common.params.DefaultSolrParams:{params(df=TEXT&alternativeDic=DEFAULT_DICTIONARY&fl=DBID,score&start=0&fq={!afts}AUTHORITY_FILTER_FROM_JSON&fq={!afts}TENANT_FILTER_FROM_JSON&rows=1000&locale=en_US&wt=json),defaults(carrot.url=id&spellcheck.collateExtendedResults=true&carrot.produceSummary=true&spellcheck.maxCollations=3&spellcheck.maxCollationTries=5&spellcheck.alternativeTermCount=2&spellcheck.extendedResults=false&defType=afts&spellcheck.maxResultsForSuggest=5&spellcheck=false&carrot.outputSubClusters=false&spellcheck.count=5&carrot.title=mltext@m___t@{http://www.alfresco.org/model/content/1.0}title&carrot.snippet=content@s___t@{http://www.alfresco.org/model/content/1.0}content&spellcheck.collate=true)}\",\"_field_mappings_\":{},\"_date_mappings_\":{},\"_range_mappings_\":{},\"_pivot_mappings_\":{},\"_interval_mappings_\":{},\"_stats_field_mappings_\":{},\"_stats_facet_mappings_\":{},\"_facet_function_mappings_\":{},\"response\":{\"numFound\":6,\"start\":0,\"maxScore\":0.7849362,\"docs\":[{\"DBID\":565,\"score\":0.7849362},{\"DBID\":566,\"score\":0.7849362},{\"DBID\":521,\"score\":0.3540957},{\"DBID\":514,\"score\":0.33025497},{\"DBID\":420,\"score\":0.32440513},{\"DBID\":415,\"score\":0.2780319}]},"
|
||||||
|
+ "\"spellcheck\":{\"searchInsteadFor\":\"alfresco\"},"
|
||||||
|
+ "\"facet_counts\":{\"facet_queries\": {\"small\": 52,\"large\": 0,\"medium\": 0}},"
|
||||||
|
+ "\"processedDenies\":true, \"lastIndexedTx\":34}";
|
||||||
|
|
||||||
|
ResultSet results = mockResultset(expectedResponse);
|
||||||
|
SearchQuery searchQuery = helper.extractFromJson(jsonQuery);
|
||||||
|
SearchContext searchContext = mapper.toSearchContext((SolrJSONResultSet) results, searchQuery, 0);
|
||||||
|
assertEquals(34l, searchContext.getConsistency().getlastTxId());
|
||||||
|
assertEquals(null, searchContext.getFacetQueries());
|
||||||
|
assertEquals(1, searchContext.getFacetsFields().size());
|
||||||
|
assertEquals(3,searchContext.getFacetsFields().get(0).getBuckets().size());
|
||||||
|
assertEquals("small",searchContext.getFacetsFields().get(0).getBuckets().get(0).getLabel());
|
||||||
|
assertEquals("content.size:[o TO 102400]",searchContext.getFacetsFields().get(0).getBuckets().get(0).getFilterQuery());
|
||||||
|
assertNotNull(searchContext.getFacetsFields().get(0).getBuckets().get(0).getCount());
|
||||||
|
}
|
||||||
|
private ResultSet mockResultset(String json) throws Exception
|
||||||
|
{
|
||||||
|
NodeService nodeService = mock(NodeService.class);
|
||||||
|
JSONObject jsonObj = new JSONObject(new JSONTokener(json));
|
||||||
|
SearchParameters sp = new SearchParameters();
|
||||||
|
sp.setBulkFetchEnabled(false);
|
||||||
|
ResultSet results = new SolrJSONResultSet(jsonObj,
|
||||||
|
sp,
|
||||||
|
nodeService,
|
||||||
|
null,
|
||||||
|
LimitBy.FINAL_SIZE,
|
||||||
|
10);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
private ResultSet mockResultset(List<Long> archivedNodes, List<Long> versionNodes) throws JSONException
|
private ResultSet mockResultset(List<Long> archivedNodes, List<Long> versionNodes) throws JSONException
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@@ -387,14 +387,14 @@ public class SearchMapperTests
|
|||||||
//Doesn't error
|
//Doesn't error
|
||||||
searchMapper.fromFacetQuery(searchParameters, null);
|
searchMapper.fromFacetQuery(searchParameters, null);
|
||||||
|
|
||||||
searchMapper.fromFacetQuery(searchParameters, Arrays.asList(new FacetQuery("ping", null), new FacetQuery("pong", "table")));
|
searchMapper.fromFacetQuery(searchParameters, Arrays.asList(new FacetQuery("ping", null,null), new FacetQuery("pong", "table",null)));
|
||||||
assertEquals(2 ,searchParameters.getFacetQueries().size());
|
assertEquals(2 ,searchParameters.getFacetQueries().size());
|
||||||
assertEquals("{!afts key='ping'}ping" ,searchParameters.getFacetQueries().get(0));
|
assertEquals("{!afts key='ping'}ping" ,searchParameters.getFacetQueries().get(0));
|
||||||
assertEquals("{!afts key='table'}pong" ,searchParameters.getFacetQueries().get(1));
|
assertEquals("{!afts key='table'}pong" ,searchParameters.getFacetQueries().get(1));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
searchMapper.fromFacetQuery(searchParameters, Arrays.asList(new FacetQuery("ping", null),new FacetQuery("{!afts}pang", "tennis")));
|
searchMapper.fromFacetQuery(searchParameters, Arrays.asList(new FacetQuery("ping", null,null),new FacetQuery("{!afts}pang", "tennis",null)));
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
catch (InvalidArgumentException iae)
|
catch (InvalidArgumentException iae)
|
||||||
@@ -655,4 +655,9 @@ public class SearchMapperTests
|
|||||||
SearchQuery sq = new SearchQuery(query, 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);
|
||||||
return sq;
|
return sq;
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
public void facetGroup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -94,7 +94,7 @@ public class SerializerTestHelper implements RequestReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchQuery extractFromJson(String json) throws IOException
|
public SearchQuery extractFromJson(String json) throws IOException
|
||||||
{
|
{
|
||||||
Content content = mock(Content.class);
|
Content content = mock(Content.class);
|
||||||
when(content.getReader()).thenReturn(new StringReader(json));
|
when(content.getReader()).thenReturn(new StringReader(json));
|
||||||
|
Reference in New Issue
Block a user