From 8199f45483ad90eb9d189a3fbf64f4d2a85bfbc4 Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Mon, 19 May 2014 12:14:59 +0000 Subject: [PATCH] Merged HEAD-BUG-FIX (4.3/Cloud) to HEAD (4.3/Cloud) 70544: Merged WAT1 (4.3/Cloud) to HEAD-BUG-FIX (4.3/Cloud) 66789: Merged BRANCHES/DEV/KEVINR to BRANCHES/DEV/WAT1 (all faceted search prototype commits) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@70774 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/repo/jscript/Search.java | 82 ++++++++++++++++++- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/source/java/org/alfresco/repo/jscript/Search.java b/source/java/org/alfresco/repo/jscript/Search.java index d766ba2298..fbadf17b82 100644 --- a/source/java/org/alfresco/repo/jscript/Search.java +++ b/source/java/org/alfresco/repo/jscript/Search.java @@ -39,11 +39,13 @@ import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchParameters.FieldFacet; import org.alfresco.service.cmr.search.SearchParameters.Operator; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.util.ISO9075; +import org.alfresco.util.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; @@ -501,6 +503,7 @@ public class Search extends BaseScopableProcessorExtension * namespace: string, optional, the default namespace for properties * defaultField: string, optional, the default field for query elements when not explicit in the query * defaultOperator: string,optional, the default operator for query elements when they are not explicit in the query AND or OR + * fieldFacets: [], optional, Array of fields (as full QName strings) to facet against * onerror: string optional, result on error - one of: exception, no-results - defaults to 'exception' * } * @@ -532,8 +535,14 @@ public class Search extends BaseScopableProcessorExtension * @return Array of ScriptNode results */ public Scriptable query(Object search) + { + return (Scriptable)queryResultSet(search).get("nodes", getScope()); + } + + public Scriptable queryResultSet(Object search) { Object[] results = null; + Map meta = null; // convert values from JS to Java - may contain native JS object such as ConsString etc. search = new ValueConverter().convertValueForJava(search); @@ -556,6 +565,7 @@ public class Search extends BaseScopableProcessorExtension String language = (String)def.get("language"); List> sort = (List>)def.get("sort"); Map page = (Map)def.get("page"); + List facets = (List)def.get("fieldFacets"); String namespace = (String)def.get("namespace"); String onerror = (String)def.get("onerror"); String defaultField = (String)def.get("defaultField"); @@ -676,6 +686,13 @@ public class Search extends BaseScopableProcessorExtension sp.addQueryTemplate(field, queryTemplates.get(field)); } } + if (facets != null) + { + for (String field: facets) + { + sp.addFieldFacet(new FieldFacet("@" + field)); + } + } // error handling opions boolean exceptionOnError = true; @@ -696,7 +713,9 @@ public class Search extends BaseScopableProcessorExtension } // execute search based on search definition - results = query(sp, exceptionOnError); + Pair> r = queryResultMeta(sp, exceptionOnError); + results = r.getFirst(); + meta = r.getSecond(); } } @@ -705,7 +724,25 @@ public class Search extends BaseScopableProcessorExtension results = new Object[0]; } - return Context.getCurrentContext().newArray(getScope(), results); + // construct a JS return object + // { + // nodes: [], // Array of ScriptNode results + // meta: { + // numberFound: long, // total number found in index, or -1 if not known or not supported by this resultset + // facets: { // facets are returned for each field as requested in the SearchParameters fieldfacets + // field: { // each field contains a map of facet to value + // facet: value, + // ... + // }, + // ... + // } + // } + // } + Scriptable scope = getScope(); + Scriptable res = Context.getCurrentContext().newObject(scope); + res.put("nodes", res, Context.getCurrentContext().newArray(scope, results)); + res.put("meta", res, meta); + return res; } /** @@ -803,8 +840,25 @@ public class Search extends BaseScopableProcessorExtension * @return Array of Node objects */ protected Object[] query(SearchParameters sp, boolean exceptionOnError) - { + { + return queryResultMeta(sp, exceptionOnError).getFirst(); + } + + /** + * Execute the query + * + * Removes any duplicates that may be present (ID search can cause duplicates - + * it is better to remove them here) + * + * @param sp SearchParameters describing the search to execute. + * @param exceptionOnError True to throw a runtime exception on error, false to return empty resultset + * + * @return Pair containing Object[] of Node objects, and the ResultSet metadata hash. + */ + protected Pair> queryResultMeta(SearchParameters sp, boolean exceptionOnError) + { Collection set = null; + Map meta = new HashMap<>(8); long time = 0L; if (logger.isDebugEnabled()) @@ -819,6 +873,7 @@ public class Search extends BaseScopableProcessorExtension { results = this.services.getSearchService().query(sp); + // results nodes if (results.length() != 0) { NodeService nodeService = this.services.getNodeService(); @@ -832,6 +887,24 @@ public class Search extends BaseScopableProcessorExtension } } } + // results metadata + meta.put("numberFound", results.getNumberFound()); + meta.put("hasMore", results.hasMore()); + // results facets + Map> facetMeta = new HashMap<>(); + for (FieldFacet ff: sp.getFieldFacets()) + { + // for each field facet, get the facet results + List> fs = results.getFieldFacet(ff.getField()); + HashMap facets = new HashMap<>(); + for (Pair f: fs) + { + facets.put(f.getFirst(), f.getSecond()); + } + // store facet results per field + facetMeta.put(ff.getField(), facets); + } + meta.put("facets", facetMeta); } catch (Throwable err) { @@ -854,7 +927,8 @@ public class Search extends BaseScopableProcessorExtension logger.debug("query time: " + (System.currentTimeMillis()-time) + "ms"); } - return set != null ? set.toArray(new Object[(set.size())]) : new Object[0]; + Object[] res = set != null ? set.toArray(new Object[(set.size())]) : new Object[0]; + return new Pair>(res, meta); }