Index: oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java =================================================================== --- oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java (revision 1716438) +++ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java (working copy) @@ -218,6 +218,8 @@ private final boolean saveDirListing; + private final boolean suggestAnalyzed; + public IndexDefinition(NodeState root, NodeState defn) { this(root, defn, null); } @@ -283,6 +285,7 @@ this.pathFilter = PathFilter.from(new ReadOnlyBuilder(defn)); this.queryPaths = getQueryPaths(defn); this.saveDirListing = getOptionalValue(defn, LuceneIndexConstants.SAVE_DIR_LISTING, true); + this.suggestAnalyzed = getOptionalValue(defn, LuceneIndexConstants.SUGGEST_ANALYZED, false); } public boolean isFullTextEnabled() { @@ -624,6 +627,10 @@ return definition.getString(LuceneIndexConstants.INDEX_PATH); } + public boolean isSuggestAnalyzed() { + return suggestAnalyzed; + } + public class IndexingRule { private final String baseNodeType; private final String nodeTypeName; Index: oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java =================================================================== --- oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java (revision 1716438) +++ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java (working copy) @@ -284,4 +284,10 @@ * existing index files */ String INDEX_PATH = "indexPath"; + + /** + * Optional property to set the suggest field to be analyzed and therefore allow more fine + * grained and flexible suggestions. + */ + String SUGGEST_ANALYZED = "suggestAnalyzed"; } Index: oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java =================================================================== --- oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java (revision 1716438) +++ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java (working copy) @@ -16,12 +16,8 @@ */ package org.apache.jackrabbit.oak.plugins.index.lucene; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount; -import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PERSISTENCE_PATH; -import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.VERSION; -import static org.apache.lucene.store.NoLockFactory.getNoLockFactory; - +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -32,9 +28,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import org.apache.commons.io.IOUtils; import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.PropertyState; @@ -62,6 +55,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount; +import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PERSISTENCE_PATH; +import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.VERSION; +import static org.apache.lucene.store.NoLockFactory.getNoLockFactory; + public class LuceneIndexEditorContext { private static final Logger log = LoggerFactory @@ -79,7 +78,9 @@ Analyzer definitionAnalyzer = definition.getAnalyzer(); Map analyzers = new HashMap(); analyzers.put(FieldNames.SPELLCHECK, new ShingleAnalyzerWrapper(LuceneIndexConstants.ANALYZER, 3)); - analyzers.put(FieldNames.SUGGEST, SuggestHelper.getAnalyzer()); + if (!definition.isSuggestAnalyzed()) { + analyzers.put(FieldNames.SUGGEST, SuggestHelper.getAnalyzer()); + } Analyzer analyzer = new PerFieldAnalyzerWrapper(definitionAnalyzer, analyzers); IndexWriterConfig config = new IndexWriterConfig(VERSION, analyzer); if (remoteDir) { Index: oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/CRTokenizer.java =================================================================== --- oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/CRTokenizer.java (revision 1716438) +++ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/CRTokenizer.java (working copy) @@ -25,10 +25,8 @@ /** * A {@link org.apache.lucene.analysis.util.CharTokenizer} dividing tokens at \n. - *

- * This should be deprecated/removed and not used anymore in {@link org.apache.jackrabbit.oak.plugins.index.lucene.util.SuggestHelper} - * (and related 'suggest fields merging code' removed in {@link org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditor}) - * if / once LUCENE-5833 fix gets included in the Lucene version we ship. + * + * This should be deprecated if / once LUCENE-5833 fix gets included in the Lucene version we ship. */ public class CRTokenizer extends CharTokenizer { public CRTokenizer(Version matchVersion, Reader input) { Index: oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/SuggestTest.java =================================================================== --- oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/SuggestTest.java (revision 1716438) +++ oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/SuggestTest.java (working copy) @@ -31,6 +31,7 @@ import org.apache.jackrabbit.core.query.AbstractQueryTest; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import java.util.List; @@ -106,6 +107,30 @@ assertTrue(result.contains("in 2015 my fox is red, like mike's fox and john's fox")); } + @Ignore + public void testSuggestAnalyzed() throws Exception { + superuser.getNode("/oak:index/luceneGlobal").setProperty("suggestAnalyzed", true); + + try { + Session session = superuser; + QueryManager qm = session.getWorkspace().getQueryManager(); + Node n1 = testRootNode.addNode("node1"); + n1.setProperty("jcr:title", "all along 2015 my fox has been red, like mike's fox and john's fox"); + Node n2 = testRootNode.addNode("node2"); + n2.setProperty("jcr:title", "in 2015 a red fox is still a fox, although not jeff's fox"); + session.save(); + + String xpath = "/jcr:root[rep:suggest('al')]/(rep:suggest())"; + Query q = qm.createQuery(xpath, Query.XPATH); + List result = getResult(q.execute(), "rep:suggest()"); + assertNotNull(result); + assertTrue(result.contains("all")); + assertTrue(result.contains("although")); + } finally { + superuser.getNode("/oak:index/luceneGlobal").setProperty("suggestAnalyzed", false); + } + } + public void testNoSuggestions() throws Exception { Session session = superuser; QueryManager qm = session.getWorkspace().getQueryManager(); Index: oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexSuggestionTest.java =================================================================== --- oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexSuggestionTest.java (revision 1716438) +++ oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexSuggestionTest.java (working copy) @@ -71,7 +71,7 @@ root = session.getRootNode(); } - private void createSuggestIndex(String name, String indexedNodeType, String indexedPropertyName, boolean addFullText) + private void createSuggestIndex(String name, String indexedNodeType, String indexedPropertyName, boolean addFullText, boolean analyzed) throws Exception { Node def = root.getNode(INDEX_DEFINITIONS_NAME) .addNode(name, INDEX_DEFINITIONS_NODE_TYPE); @@ -85,7 +85,7 @@ .addNode(LuceneIndexConstants.PROP_NODE, JcrConstants.NT_UNSTRUCTURED) .addNode("indexedProperty", JcrConstants.NT_UNSTRUCTURED); propertyIdxDef.setProperty("propertyIndex", true); - propertyIdxDef.setProperty("analyzed", true); + propertyIdxDef.setProperty("analyzed", analyzed); propertyIdxDef.setProperty("useInSuggest", true); if (addFullText) { propertyIdxDef.setProperty("nodeScopeIndex", true); @@ -100,12 +100,12 @@ private void checkSuggestions(final String nodeType, final String indexPropName, final String indexPropValue, final boolean addFullText, final boolean useUserSession, - final String suggestQueryText, final boolean shouldSuggest) + final String suggestQueryText, final boolean shouldSuggest, final boolean analyed) throws Exception { checkSuggestions(nodeType, nodeType, indexPropName, indexPropValue, addFullText, useUserSession, - suggestQueryText, shouldSuggest); + suggestQueryText, shouldSuggest, analyed); } /** @@ -115,9 +115,10 @@ private void checkSuggestions(final String indexNodeType, final String queryNodeType, final String indexPropName, final String indexPropValue, final boolean addFullText, final boolean useUserSession, - final String suggestQueryText, final boolean shouldSuggest) + final String suggestQueryText, final boolean shouldSuggest, + final boolean analyzed) throws Exception { - createSuggestIndex("lucene-suggest", indexNodeType, indexPropName, addFullText); + createSuggestIndex("lucene-suggest", indexNodeType, indexPropName, addFullText, analyzed); Node indexedNode = root.addNode("indexedNode1", queryNodeType); indexedNode.setProperty(indexPropName, indexPropValue + " 1"); @@ -170,7 +171,7 @@ checkSuggestions(nodeType, indexPropName, indexPropValue, false, false, - suggestQueryText, shouldSuggest); + suggestQueryText, shouldSuggest, true); } //OAK-3156 @@ -185,7 +186,7 @@ checkSuggestions(nodeType, indexPropName, indexPropValue, false, true, - suggestQueryText, shouldSuggest); + suggestQueryText, shouldSuggest, true); } //OAK-3156 @@ -201,7 +202,7 @@ checkSuggestions(indexNodeType, queryNodeType, indexPropName, indexPropValue, true, false, - suggestQueryText, shouldSuggest); + suggestQueryText, shouldSuggest, false); } //OAK-3156 @@ -216,7 +217,7 @@ checkSuggestions(nodeType, indexPropName, indexPropValue, true, false, - suggestQueryText, shouldSuggest); + suggestQueryText, shouldSuggest, false); } //OAK-3509 @@ -231,6 +232,6 @@ checkSuggestions(nodeType, indexPropName, indexPropValue, true, false, - suggestQueryText, shouldSuggest); + suggestQueryText, shouldSuggest, false); } }