Fix for ALF-3776: Query sorting is not support on .size and .mimetype properties of content.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20934 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Andrew Hind
2010-07-05 13:17:19 +00:00
parent 98c5de7ffe
commit ca5fa3a973
3 changed files with 266 additions and 117 deletions

View File

@@ -316,85 +316,112 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
field = expandAttributeFieldName(field);
PropertyDefinition propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1)));
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
throw new SearcherException("Order on content properties is not curently supported");
}
else if ((propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))
|| (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)))
{
List<Locale> locales = searchParameters.getLocales();
if (((locales == null) || (locales.size() == 0)))
// Handle .size and .mimetype
if(propertyDef == null)
{
if(field.endsWith(".size"))
{
locales = Collections.singletonList(I18NUtil.getLocale());
}
if (locales.size() > 1)
{
throw new SearcherException("Order on text/mltext properties with more than one locale is not curently supported");
}
sortLocale = locales.get(0);
// find best field match
MLAnalysisMode analysisMode = getLuceneConfig().getDefaultMLSearchAnalysisMode();
HashSet<String> allowableLocales = new HashSet<String>();
for (Locale l : MLAnalysisMode.getLocales(analysisMode, sortLocale, false))
{
allowableLocales.add(l.toString());
}
String sortField = field;
for (Object current : searcher.getReader().getFieldNames(FieldOption.INDEXED))
{
String currentString = (String) current;
if (currentString.startsWith(field) && currentString.endsWith(".sort"))
propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1, field.length()-5)));
if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
String fieldLocale = currentString.substring(field.length() + 1, currentString.length() - 5);
if (allowableLocales.contains(fieldLocale))
throw new SearcherException("Order for .size only supported on content properties");
}
}
else if (field.endsWith(".mimetype"))
{
propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1, field.length()-9)));
if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
throw new SearcherException("Order for .mimetype only supported on content properties");
}
}
else
{
// nothing
}
}
else
{
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
throw new SearcherException("Order on content properties is not curently supported");
}
else if ((propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))
|| (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)))
{
List<Locale> locales = searchParameters.getLocales();
if (((locales == null) || (locales.size() == 0)))
{
locales = Collections.singletonList(I18NUtil.getLocale());
}
if (locales.size() > 1)
{
throw new SearcherException("Order on text/mltext properties with more than one locale is not curently supported");
}
sortLocale = locales.get(0);
// find best field match
MLAnalysisMode analysisMode = getLuceneConfig().getDefaultMLSearchAnalysisMode();
HashSet<String> allowableLocales = new HashSet<String>();
for (Locale l : MLAnalysisMode.getLocales(analysisMode, sortLocale, false))
{
allowableLocales.add(l.toString());
}
String sortField = field;
for (Object current : searcher.getReader().getFieldNames(FieldOption.INDEXED))
{
String currentString = (String) current;
if (currentString.startsWith(field) && currentString.endsWith(".sort"))
{
if (fieldLocale.equals(sortLocale.toString()))
String fieldLocale = currentString.substring(field.length() + 1, currentString.length() - 5);
if (allowableLocales.contains(fieldLocale))
{
sortField = currentString;
break;
}
else if (sortLocale.toString().startsWith(fieldLocale))
{
if (sortField.equals(field) || (currentString.length() < sortField.length()))
if (fieldLocale.equals(sortLocale.toString()))
{
sortField = currentString;
break;
}
}
else if (fieldLocale.startsWith(sortLocale.toString()))
{
if (sortField.equals(field) || (currentString.length() < sortField.length()))
else if (sortLocale.toString().startsWith(fieldLocale))
{
sortField = currentString;
if (sortField.equals(field) || (currentString.length() < sortField.length()))
{
sortField = currentString;
}
}
else if (fieldLocale.startsWith(sortLocale.toString()))
{
if (sortField.equals(field) || (currentString.length() < sortField.length()))
{
sortField = currentString;
}
}
}
}
}
}
field = sortField;
field = sortField;
}
else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
{
DataTypeDefinition dataType = propertyDef.getDataType();
String analyserClassName = dataType.getAnalyserClassName();
if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
{
field = field + ".sort";
}
else
else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
{
requiresPostSort = true;
DataTypeDefinition dataType = propertyDef.getDataType();
String analyserClassName = dataType.getAnalyserClassName();
if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
{
field = field + ".sort";
}
else
{
requiresPostSort = true;
}
}
}
}
if (fieldHasTerm(searcher.getReader(), field))
{
fields[index++] = new SortField(field, sortLocale, !sd.isAscending());

View File

@@ -1228,6 +1228,38 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener
ftsQueryWithCount(searcher, "modified:*", 2, Arrays.asList(new NodeRef[]{n14,n15}));
ftsQueryWithCount(searcher, "modified:[MIN TO NOW]", 2, Arrays.asList(new NodeRef[]{n14,n15}));
}
private ADMLuceneSearcherImpl buildSearcher()
{
ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher);
searcher.setNodeService(nodeService);
searcher.setDictionaryService(dictionaryService);
searcher.setTenantService(tenantService);
searcher.setNamespacePrefixResolver(getNamespacePrefixResolver("namespace"));
searcher.setQueryRegister(queryRegisterComponent);
searcher.setQueryLanguages(((AbstractLuceneIndexerAndSearcherFactory) indexerAndSearcher).queryLanguages);
return searcher;
}
public void testFTSandSort() throws Exception
{
luceneFTS.pause();
buildBaseIndex();
ADMLuceneSearcherImpl searcher = buildSearcher();
SearchParameters sp = new SearchParameters();
sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
sp.addStore(rootNodeRef.getStoreRef());
sp.setQuery( "PATH:\"//.\"");
sp.addQueryTemplate("ANDY", "%cm:content");
sp.setNamespace(NamespaceService.CONTENT_MODEL_1_0_URI);
sp.excludeDataInTheCurrentTransaction(true);
sp.addSort("@"+ContentModel.PROP_CONTENT.toString()+".size", true);
ResultSet results = searcher.query(sp);
assertEquals(16, results.length());
results.close();
}
public void ftsQueryWithCount(ADMLuceneSearcherImpl searcher, String query, int count)
{
@@ -2960,6 +2992,10 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener
}
results.close();
// sort by content size
// sort by ML text
//Locale[] testLocales = new Locale[] { I18NUtil.getLocale(), Locale.ENGLISH, Locale.FRENCH, Locale.CHINESE };
@@ -3030,6 +3066,58 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener
results.close();
luceneFTS.resume();
// sort by content size
SearchParameters sp20 = new SearchParameters();
sp20.addStore(rootNodeRef.getStoreRef());
sp20.setLanguage(SearchService.LANGUAGE_LUCENE);
sp20.setQuery("PATH:\"//.\"");
sp20.addSort("@" + ContentModel.PROP_CONTENT+".size", false);
results = searcher.query(sp20);
Long size = null;
for (ResultSetRow row : results)
{
ContentData currentBun = DefaultTypeConverter.INSTANCE.convert(ContentData.class, nodeService.getProperty(row.getNodeRef(), ContentModel.PROP_CONTENT));
// System.out.println(currentBun);
if ((size != null) && (currentBun != null))
{
assertTrue(size.compareTo(currentBun.getSize()) >= 0);
}
if(currentBun != null)
{
size = currentBun.getSize();
}
}
results.close();
// sort by content mimetype
SearchParameters sp21 = new SearchParameters();
sp21.addStore(rootNodeRef.getStoreRef());
sp21.setLanguage(SearchService.LANGUAGE_LUCENE);
sp21.setQuery("PATH:\"//.\"");
sp21.addSort("@" + ContentModel.PROP_CONTENT+".mimetype", false);
results = searcher.query(sp21);
String mimetype = null;
for (ResultSetRow row : results)
{
ContentData currentBun = DefaultTypeConverter.INSTANCE.convert(ContentData.class, nodeService.getProperty(row.getNodeRef(), ContentModel.PROP_CONTENT));
// System.out.println(currentBun);
if ((mimetype != null) && (currentBun != null))
{
assertTrue(mimetype.compareTo(currentBun.getMimetype()) >= 0);
}
if(currentBun != null)
{
mimetype = currentBun.getMimetype();
}
}
results.close();
}
/**

View File

@@ -157,79 +157,113 @@ public class AlfrescoFunctionEvaluationContext implements FunctionEvaluationCont
{
PropertyDefinition propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1)));
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
throw new SearcherException("Order on content properties is not curently supported");
}
else if ((propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) || (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)))
{
List<Locale> locales = lqp.getSearchParameters().getLocales();
if (((locales == null) || (locales.size() == 0)))
// Handle .size and .mimetype
if(propertyDef == null)
{
if(field.endsWith(".size"))
{
locales = Collections.singletonList(I18NUtil.getLocale());
}
if (locales.size() > 1)
{
throw new SearcherException("Order on text/mltext properties with more than one locale is not curently supported");
}
sortLocale = locales.get(0);
// find best field match
HashSet<String> allowableLocales = new HashSet<String>();
MLAnalysisMode analysisMode = lqp.getConfig().getDefaultMLSearchAnalysisMode();
for (Locale l : MLAnalysisMode.getLocales(analysisMode, sortLocale, false))
{
allowableLocales.add(l.toString());
}
String sortField = field;
for (Object current : lqp.getIndexReader().getFieldNames(FieldOption.INDEXED))
{
String currentString = (String) current;
if (currentString.startsWith(field) && currentString.endsWith(".sort"))
propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1, field.length()-5)));
if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
String fieldLocale = currentString.substring(field.length() + 1, currentString.length() - 5);
if (allowableLocales.contains(fieldLocale))
throw new SearcherException("Order for .size only supported on content properties");
}
else
{
return field;
}
}
else if (field.endsWith(".mimetype"))
{
propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1, field.length()-9)));
if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
throw new SearcherException("Order for .mimetype only supported on content properties");
}
else
{
return field;
}
}
else
{
return field;
}
}
else
{
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
throw new SearcherException("Order on content properties is not curently supported");
}
else if ((propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) || (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)))
{
List<Locale> locales = lqp.getSearchParameters().getLocales();
if (((locales == null) || (locales.size() == 0)))
{
locales = Collections.singletonList(I18NUtil.getLocale());
}
if (locales.size() > 1)
{
throw new SearcherException("Order on text/mltext properties with more than one locale is not curently supported");
}
sortLocale = locales.get(0);
// find best field match
HashSet<String> allowableLocales = new HashSet<String>();
MLAnalysisMode analysisMode = lqp.getConfig().getDefaultMLSearchAnalysisMode();
for (Locale l : MLAnalysisMode.getLocales(analysisMode, sortLocale, false))
{
allowableLocales.add(l.toString());
}
String sortField = field;
for (Object current : lqp.getIndexReader().getFieldNames(FieldOption.INDEXED))
{
String currentString = (String) current;
if (currentString.startsWith(field) && currentString.endsWith(".sort"))
{
if (fieldLocale.equals(sortLocale.toString()))
String fieldLocale = currentString.substring(field.length() + 1, currentString.length() - 5);
if (allowableLocales.contains(fieldLocale))
{
sortField = currentString;
break;
}
else if (sortLocale.toString().startsWith(fieldLocale))
{
if (sortField.equals(field) || (currentString.length() < sortField.length()))
if (fieldLocale.equals(sortLocale.toString()))
{
sortField = currentString;
break;
}
}
else if (fieldLocale.startsWith(sortLocale.toString()))
{
if (sortField.equals(field) || (currentString.length() < sortField.length()))
else if (sortLocale.toString().startsWith(fieldLocale))
{
sortField = currentString;
if (sortField.equals(field) || (currentString.length() < sortField.length()))
{
sortField = currentString;
}
}
else if (fieldLocale.startsWith(sortLocale.toString()))
{
if (sortField.equals(field) || (currentString.length() < sortField.length()))
{
sortField = currentString;
}
}
}
}
}
field = sortField;
}
field = sortField;
}
else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
{
DataTypeDefinition dataType = propertyDef.getDataType();
String analyserClassName = dataType.getAnalyserClassName();
if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
{
field = field + ".sort";
DataTypeDefinition dataType = propertyDef.getDataType();
String analyserClassName = dataType.getAnalyserClassName();
if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
{
field = field + ".sort";
}
}
}
}
return field;
}