From ca5fa3a97328fdce75326617aadf9bb7fdc571b6 Mon Sep 17 00:00:00 2001 From: Andrew Hind Date: Mon, 5 Jul 2010 13:17:19 +0000 Subject: [PATCH] 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 --- .../impl/lucene/ADMLuceneSearcherImpl.java | 147 ++++++++++------- .../search/impl/lucene/ADMLuceneTest.java | 88 +++++++++++ .../AlfrescoFunctionEvaluationContext.java | 148 +++++++++++------- 3 files changed, 266 insertions(+), 117 deletions(-) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java index 6dca07c25e..c921269233 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java @@ -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 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 allowableLocales = new HashSet(); - 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 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 allowableLocales = new HashSet(); + 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()); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java index 1a5a5689c9..9df7a86c0b 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -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(); + } /** diff --git a/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java b/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java index 5d2c1bf8e4..c24f4eed43 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java @@ -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 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 allowableLocales = new HashSet(); - 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 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 allowableLocales = new HashSet(); + 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; }