Tag cloud support

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7449 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Andrew Hind
2007-11-27 16:20:01 +00:00
parent 08f0ed882c
commit 0b19ebb616
9 changed files with 317 additions and 77 deletions

View File

@@ -28,8 +28,11 @@ import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
@@ -58,6 +61,7 @@ import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.Pair;
import org.springframework.context.ApplicationContext;
/**
@@ -282,7 +286,7 @@ public class ADMLuceneCategoryTest extends TestCase
genCatProp.setMandatory(true);
genCatProp.setMultiValued(true);
genCatProp.setStoredInIndex(true);
genCatProp.setTokenisedInIndex(true);
genCatProp.setTokenisedInIndex(false);
genCatProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
assetClassCategorisationQName = QName.createQName(TEST_NAMESPACE, "AssetClass");
@@ -294,7 +298,7 @@ public class ADMLuceneCategoryTest extends TestCase
acProp.setMandatory(true);
acProp.setMultiValued(true);
acProp.setStoredInIndex(true);
acProp.setTokenisedInIndex(true);
acProp.setTokenisedInIndex(false);
acProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
investmentRegionCategorisationQName = QName.createQName(TEST_NAMESPACE, "InvestmentRegion");
@@ -306,7 +310,7 @@ public class ADMLuceneCategoryTest extends TestCase
irProp.setMandatory(true);
irProp.setMultiValued(true);
irProp.setStoredInIndex(true);
irProp.setTokenisedInIndex(true);
irProp.setTokenisedInIndex(false);
irProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
marketingRegionCategorisationQName = QName.createQName(TEST_NAMESPACE, "MarketingRegion");
@@ -318,7 +322,7 @@ public class ADMLuceneCategoryTest extends TestCase
mrProp.setMandatory(true);
mrProp.setMultiValued(true);
mrProp.setStoredInIndex(true);
mrProp.setTokenisedInIndex(true);
mrProp.setTokenisedInIndex(false);
mrProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
dictionaryDAO.putModel(model);
@@ -798,6 +802,52 @@ public class ADMLuceneCategoryTest extends TestCase
}
public void testCatCount() throws Exception
{
TransactionService transactionService = serviceRegistry.getTransactionService();
UserTransaction tx = transactionService.getUserTransaction();
tx.begin();
assertEquals(1, categoryService.getChildren(catACBase , CategoryService.Mode.MEMBERS, CategoryService.Depth.IMMEDIATE).size());
assertEquals(2, categoryService.getChildren(catACBase , CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.IMMEDIATE).size());
assertEquals(3, categoryService.getChildren(catACBase , CategoryService.Mode.ALL, CategoryService.Depth.IMMEDIATE).size());
assertEquals(14, categoryService.getChildren(catACBase , CategoryService.Mode.MEMBERS, CategoryService.Depth.ANY).size());
assertEquals(3, categoryService.getChildren(catACBase , CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.ANY).size());
assertEquals(17, categoryService.getChildren(catACBase , CategoryService.Mode.ALL, CategoryService.Depth.ANY).size());
assertEquals(2, categoryService.getClassifications(rootNodeRef.getStoreRef()).size());
assertEquals(2, categoryService.getCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass"), CategoryService.Depth.IMMEDIATE).size());
assertEquals(3, categoryService.getCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass"), CategoryService.Depth.ANY).size());
assertEquals(6, categoryService.getClassificationAspects().size());
assertEquals(2, categoryService.getRootCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass")).size());
List<Pair<NodeRef, Integer>> top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass"), 10);
for(Pair<NodeRef, Integer> current : top)
{
System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
}
top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "InvestmentRegion"), 10);
for(Pair<NodeRef, Integer> current : top)
{
System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
}
top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "MarketingRegion"), 10);
for(Pair<NodeRef, Integer> current : top)
{
System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
}
top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "Region"), 10);
for(Pair<NodeRef, Integer> current : top)
{
System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
}
tx.commit();
}
@SuppressWarnings("unused")
private int getTotalScore(ResultSet results)
{

View File

@@ -27,8 +27,10 @@ package org.alfresco.repo.search.impl.lucene;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -60,11 +62,13 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.alfresco.util.Pair;
import org.alfresco.util.SearchLanguageConversion;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.TermEnum;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Query;
@@ -93,7 +97,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
private NamespacePrefixResolver namespacePrefixResolver;
private NodeService nodeService;
private TenantService tenantService;
private QueryRegisterComponent queryRegister;
@@ -156,13 +160,12 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
{
this.nodeService = nodeService;
}
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
/**
* Set the query register
*
@@ -175,8 +178,8 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
public ResultSet query(StoreRef store, String language, String queryString, Path[] queryOptions, QueryParameterDefinition[] queryParameterDefinitions) throws SearcherException
{
store = tenantService.getName(store);
store = tenantService.getName(store);
SearchParameters sp = new SearchParameters();
sp.addStore(store);
sp.setLanguage(language);
@@ -206,9 +209,9 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
{
throw new IllegalStateException("Only one store can be searched at present");
}
ArrayList<StoreRef> stores = searchParameters.getStores();
stores.set(0, tenantService.getName(searchParameters.getStores().get(0)));
stores.set(0, tenantService.getName(searchParameters.getStores().get(0)));
String parameterisedQueryString;
if (searchParameters.getQueryParameterDefinitions().size() > 0)
@@ -243,18 +246,9 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
}
ClosingIndexSearcher searcher = getSearcher(indexer);
Query query = LuceneQueryParser.parse(
parameterisedQueryString, DEFAULT_FIELD,
new LuceneAnalyser(
getDictionaryService(),
searchParameters.getMlAnalaysisMode() == null ? getLuceneConfig().getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode()),
namespacePrefixResolver,
getDictionaryService(),
tenantService,
defaultOperator,
searchParameters,
getLuceneConfig(),
searcher.getIndexReader());
Query query = LuceneQueryParser.parse(parameterisedQueryString, DEFAULT_FIELD, new LuceneAnalyser(getDictionaryService(),
searchParameters.getMlAnalaysisMode() == null ? getLuceneConfig().getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode()),
namespacePrefixResolver, getDictionaryService(), tenantService, defaultOperator, searchParameters, getLuceneConfig(), searcher.getIndexReader());
if (s_logger.isDebugEnabled())
{
s_logger.debug("Query is " + query.toString());
@@ -277,24 +271,24 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
{
case FIELD:
String field = sd.getField();
if(field.startsWith("@"))
if (field.startsWith("@"))
{
field = expandAttributeFieldName(field);
PropertyDefinition propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1)));
field = expandAttributeFieldName(field);
PropertyDefinition propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1)));
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
{
DataTypeDefinition dataType = propertyDef.getDataType();
String analyserClassName = dataType.getAnalyserClassName();
if(analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
{
field = field + ".sort";
}
}
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
{
DataTypeDefinition dataType = propertyDef.getDataType();
String analyserClassName = dataType.getAnalyserClassName();
if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
{
field = field + ".sort";
}
}
}
if (fieldHasTerm(searcher.getReader(), field))
{
{
fields[index++] = new SortField(field, !sd.isAscending());
}
else
@@ -319,13 +313,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
}
Path[] paths = searchParameters.getAttributePaths().toArray(new Path[0]);
return new LuceneResultSet(
hits,
searcher,
nodeService,
tenantService,
paths,
searchParameters);
return new LuceneResultSet(hits, searcher, nodeService, tenantService, paths, searchParameters);
}
catch (ParseException e)
{
@@ -358,13 +346,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
return new EmptyResultSet();
}
Hits hits = searcher.search(query);
return new LuceneResultSet(
hits,
searcher,
nodeService,
tenantService,
searchParameters.getAttributePaths().toArray(new Path[0]),
searchParameters);
return new LuceneResultSet(hits, searcher, nodeService, tenantService, searchParameters.getAttributePaths().toArray(new Path[0]), searchParameters);
}
catch (SAXPathException e)
{
@@ -584,9 +566,9 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
boolean followAllParentLinks, String language) throws InvalidNodeRefException, XPathException
{
NodeSearcher nodeSearcher = new NodeSearcher(nodeService, getDictionaryService(), this);
contextNodeRef = tenantService.getName(contextNodeRef);
return nodeSearcher.selectNodes(contextNodeRef, xpath, parameters, namespacePrefixResolver, followAllParentLinks, language);
}
@@ -750,4 +732,91 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
}
return fieldName;
}
public List<Pair<String, Integer>> getTopTerms(String field, int count)
{
ClosingIndexSearcher searcher = null;
try
{
LinkedList<Pair<String, Integer>> answer = new LinkedList<Pair<String, Integer>>();
searcher = getSearcher(indexer);
IndexReader reader = searcher.getIndexReader();
TermEnum terms = reader.terms(new Term(field, ""));
while (terms.next())
{
Term term = terms.term();
if(!term.field().equals(field))
{
break;
}
int freq = terms.docFreq();
Pair<String, Integer> pair = new Pair<String, Integer>(term.text(), Integer.valueOf(freq));
if (answer.size() < count)
{
if (answer.size() == 0)
{
answer.add(pair);
}
else if (answer.get(answer.size() - 1).getSecond().compareTo(pair.getSecond()) >= 0)
{
answer.add(pair);
}
else
{
for (ListIterator<Pair<String, Integer>> it = answer.listIterator(); it.hasNext(); /**/)
{
Pair<String, Integer> test = it.next();
if (test.getSecond().compareTo(pair.getSecond()) < 0)
{
it.previous();
it.add(pair);
break;
}
}
}
}
else if (answer.get(count - 1).getSecond().compareTo(pair.getSecond()) < 0)
{
for (ListIterator<Pair<String, Integer>> it = answer.listIterator(); it.hasNext(); /**/)
{
Pair<String, Integer> test = it.next();
if (test.getSecond().compareTo(pair.getSecond()) < 0)
{
it.previous();
it.add(pair);
break;
}
}
answer.removeLast();
}
else
{
// off the end
}
}
terms.close();
return answer;
}
catch (IOException e)
{
throw new SearcherException(e);
}
finally
{
if (searcher != null)
{
try
{
searcher.close();
}
catch (IOException e)
{
throw new SearcherException(e);
}
}
}
}
}

View File

@@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -38,7 +39,10 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.IndexerAndSearcher;
import org.alfresco.repo.search.IndexerException;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -47,22 +51,25 @@ import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.alfresco.util.Pair;
/**
* Category service implementation
*
* @author andyh
*
*/
public class LuceneCategoryServiceImpl implements CategoryService
{
private NodeService nodeService;
private NodeService publicNodeService;
private TenantService tenantService;
private NamespacePrefixResolver namespacePrefixResolver;
private DictionaryService dictionaryService;
@@ -81,6 +88,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the node service
*
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
@@ -88,8 +96,19 @@ public class LuceneCategoryServiceImpl implements CategoryService
this.nodeService = nodeService;
}
/**
* Set the public node service
*
* @param nodeService
*/
public void setPublicNodeService(NodeService publicNodeService)
{
this.publicNodeService = publicNodeService;
}
/**
* Set the tenant service
*
* @param tenantService
*/
public void setTenantService(TenantService tenantService)
@@ -99,6 +118,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the service to map prefixes to uris
*
* @param namespacePrefixResolver
*/
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
@@ -108,6 +128,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the dictionary service
*
* @param dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
@@ -117,6 +138,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the indexer and searcher
*
* @param indexerAndSearcher
*/
public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher)
@@ -132,13 +154,13 @@ public class LuceneCategoryServiceImpl implements CategoryService
}
categoryRef = tenantService.getName(categoryRef);
ResultSet resultSet = null;
try
{
StringBuilder luceneQuery = new StringBuilder(64);
switch(mode)
switch (mode)
{
case ALL:
luceneQuery.append("PATH:\"");
@@ -264,15 +286,15 @@ public class LuceneCategoryServiceImpl implements CategoryService
ResultSet resultSet = null;
try
{
resultSet = indexerAndSearcher.getSearcher(storeRef, false).query(storeRef, "lucene", "PATH:\"/" + getPrefix(qname.getNamespaceURI()) + ISO9075.encode(qname.getLocalName()) + "\"",
null, null);
resultSet = indexerAndSearcher.getSearcher(storeRef, false).query(storeRef, "lucene",
"PATH:\"/" + getPrefix(qname.getNamespaceURI()) + ISO9075.encode(qname.getLocalName()) + "\"", null, null);
Set<NodeRef> nodeRefs = new HashSet<NodeRef>(resultSet.length());
for (ResultSetRow row : resultSet)
{
nodeRefs.add(row.getNodeRef());
}
return nodeRefs;
}
finally
@@ -305,7 +327,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
public Collection<QName> getClassificationAspects()
{
return dictionaryService.getSubAspects(ContentModel.ASPECT_CLASSIFIABLE, true);
return dictionaryService.getSubAspects(ContentModel.ASPECT_CLASSIFIABLE, true);
}
public NodeRef createClassifiction(StoreRef storeRef, QName typeName, String attributeName)
@@ -326,23 +348,23 @@ public class LuceneCategoryServiceImpl implements CategoryService
public NodeRef createCategory(NodeRef parent, String name)
{
if(!nodeService.exists(parent))
if (!nodeService.exists(parent))
{
throw new AlfrescoRuntimeException("Missing category?");
}
String uri = nodeService.getPrimaryParent(parent).getQName().getNamespaceURI();
String validLocalName = QName.createValidLocalName(name);
NodeRef newCategory = nodeService.createNode(parent, ContentModel.ASSOC_SUBCATEGORIES, QName.createQName(uri, validLocalName), ContentModel.TYPE_CATEGORY).getChildRef();
nodeService.setProperty(newCategory, ContentModel.PROP_NAME, name);
NodeRef newCategory = publicNodeService.createNode(parent, ContentModel.ASSOC_SUBCATEGORIES, QName.createQName(uri, validLocalName), ContentModel.TYPE_CATEGORY).getChildRef();
publicNodeService.setProperty(newCategory, ContentModel.PROP_NAME, name);
return newCategory;
}
public NodeRef createRootCategory(StoreRef storeRef, QName aspectName, String name)
{
Set<NodeRef> nodeRefs = getClassificationNodes(storeRef, aspectName);
if(nodeRefs.size() == 0)
if (nodeRefs.size() == 0)
{
throw new AlfrescoRuntimeException("Missing classification: "+aspectName);
throw new AlfrescoRuntimeException("Missing classification: " + aspectName);
}
NodeRef parent = nodeRefs.iterator().next();
return createCategory(parent, name);
@@ -350,16 +372,78 @@ public class LuceneCategoryServiceImpl implements CategoryService
public void deleteCategory(NodeRef nodeRef)
{
nodeService.deleteNode(nodeRef);
publicNodeService.deleteNode(nodeRef);
}
public void deleteClassification(StoreRef storeRef, QName aspectName)
{
throw new UnsupportedOperationException();
}
public List<Pair<NodeRef, Integer>> getTopCategories(StoreRef storeRef, QName aspectName, int count)
{
if (indexerAndSearcher instanceof LuceneIndexerAndSearcher)
{
AspectDefinition definition = dictionaryService.getAspect(aspectName);
if(definition == null)
{
throw new IllegalStateException("Unknown aspect");
}
QName catProperty = null;
Map<QName, PropertyDefinition> properties = definition.getProperties();
for(QName pName : properties.keySet())
{
if(pName.getNamespaceURI().equals(aspectName.getNamespaceURI()))
{
if(pName.getLocalName().equalsIgnoreCase(aspectName.getLocalName()))
{
PropertyDefinition def = properties.get(pName);
if(def.getDataType().getName().equals(DataTypeDefinition.CATEGORY))
{
catProperty = pName;
}
}
}
}
if(catProperty == null)
{
throw new IllegalStateException("Aspect does not have category property mirroring the aspect name");
}
LuceneIndexerAndSearcher lias = (LuceneIndexerAndSearcher) indexerAndSearcher;
String field = "@" + catProperty;
SearchService searchService = lias.getSearcher(storeRef, true);
if (searchService instanceof LuceneSearcher)
{
LuceneSearcher luceneSearcher = (LuceneSearcher)searchService;
List<Pair<String, Integer>> topTerms = luceneSearcher.getTopTerms(field, count);
List<Pair<NodeRef, Integer>> answer = new ArrayList<Pair<NodeRef, Integer>>();
for (Pair<String, Integer> term : topTerms)
{
Pair<NodeRef, Integer> toAdd;
NodeRef nodeRef = new NodeRef(term.getFirst());
if (nodeService.exists(nodeRef))
{
toAdd = new Pair<NodeRef, Integer>(nodeRef, term.getSecond());
}
else
{
toAdd = new Pair<NodeRef, Integer>(null, term.getSecond());
}
answer.add(toAdd);
}
return answer;
}
else
{
throw new UnsupportedOperationException("getPolularCategories is only supported for lucene indexes");
}
}
else
{
throw new UnsupportedOperationException("getPolularCategories is only supported for lucene indexes");
}
}
}

View File

@@ -24,8 +24,13 @@
*/
package org.alfresco.repo.search.impl.lucene;
import java.util.List;
import org.alfresco.repo.search.IndexerAndSearcher;
import org.alfresco.repo.search.IndexerException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.util.Pair;
public interface LuceneIndexerAndSearcher extends IndexerAndSearcher, LuceneConfig
{
@@ -40,4 +45,5 @@ public interface LuceneIndexerAndSearcher extends IndexerAndSearcher, LuceneConf
}
public <R> R doWithAllWriteLocks(WithAllWriteLocksWork<R> lockWork);
}

View File

@@ -24,9 +24,13 @@
*/
package org.alfresco.repo.search.impl.lucene;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.util.Pair;
/**
* Lucene implementation specific entension to the seracher API
@@ -50,4 +54,13 @@ public interface LuceneSearcher extends SearchService
* @param namespacePrefixResolver
*/
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver);
/**
* Get top terms
*
* @param field
* @param count
* @return
*/
public List<Pair<String, Integer>> getTopTerms(String field, int count);
}

View File

@@ -25,6 +25,7 @@
package org.alfresco.service.cmr.search;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.Auditable;
import org.alfresco.service.PublicService;
@@ -32,6 +33,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
/**
* Category Service
@@ -163,4 +165,14 @@ public interface CategoryService
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"nodeRef"})
public void deleteCategory(NodeRef nodeRef);
/**
* Get the most polular categories
*
* @param storeRef
* @param aspectName
* @param count
* @return
*/
public List<Pair<NodeRef, Integer>> getTopCategories(StoreRef storeRef, QName aspectName, int count);
}