diff --git a/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java b/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java index d97ffea..7752304 100644 --- a/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java +++ b/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java @@ -285,7 +285,7 @@ public class LuceneDocumentMaker extends FulltextDocumentMaker { new BytesRef(property.getValue(Type.STRING))); } - if (f != null && includePropertyValue(property, 0, pd)) { + if (f != null && doc.getField(f.name()) == null && includePropertyValue(property, 0, pd)) { doc.add(f); fieldAdded = true; } diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/FunctionIndexTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/FunctionIndexTest.java index d6656e3..93e23a0 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/FunctionIndexTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/FunctionIndexTest.java @@ -35,6 +35,7 @@ import java.util.Set; import javax.jcr.PropertyType; +import ch.qos.logback.classic.Level; import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.oak.Oak; import org.apache.jackrabbit.oak.api.ContentRepository; @@ -42,10 +43,12 @@ import org.apache.jackrabbit.oak.api.Result; import org.apache.jackrabbit.oak.api.ResultRow; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.commons.junit.LogCustomizer; import org.apache.jackrabbit.oak.plugins.index.lucene.util.IndexDefinitionBuilder; import org.apache.jackrabbit.oak.plugins.index.nodetype.NodeTypeIndexProvider; import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider; import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants; +import org.apache.jackrabbit.oak.plugins.index.search.spi.query.FulltextIndex; import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore; import org.apache.jackrabbit.oak.plugins.memory.PropertyStates; import org.apache.jackrabbit.oak.InitialContentHelper; @@ -54,6 +57,8 @@ import org.apache.jackrabbit.oak.spi.commit.Observer; import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider; import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.hamcrest.core.IsCollectionContaining; +import org.junit.Assert; import org.junit.Test; import com.google.common.collect.Iterables; @@ -339,6 +344,95 @@ public class FunctionIndexTest extends AbstractQueryTest { "lucene:test1(/oak:index/test1)", asList("/b", "/c", "/a")); } + // + @Test + public void sameOrderableRelativePropertyWithandWithoutFunction() throws Exception { + + LogCustomizer customLogs = LogCustomizer.forLogger(LuceneIndexEditor.class.getName()).enable(Level.WARN).create(); + // Create nodes that will be served by the index definition that follows + Tree test = root.getTree("/").addChild("test"); + test.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME); + + Tree a = test.addChild("jcr:content"); + a.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME); + + Tree b = a.addChild("n"); + + b.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME); + b.setProperty("foo", "bar"); + + root.commit(); + + // Index def with same property - ordered - one with function and one without + Tree luceneIndex = createIndex("upper", Collections.emptySet()); + Tree nonFunc = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES) + .addChild("nt:unstructured") + .addChild(FulltextIndexConstants.PROP_NODE) + .addChild("foo"); + nonFunc.setProperty(FulltextIndexConstants.PROP_ORDERED,true); + nonFunc.setProperty("name", "jcr:content/n/foo"); + + Tree func = luceneIndex.getChild(FulltextIndexConstants.INDEX_RULES) + .getChild("nt:unstructured") + .getChild(FulltextIndexConstants.PROP_NODE) + .addChild("testOak"); + func.setProperty(FulltextIndexConstants.PROP_ORDERED,true); + func.setProperty(FulltextIndexConstants.PROP_FUNCTION, "fn:upper-case(jcr:content/n/@foo)"); + + // Now do some change in the node that are covered by above index defintion + try { + customLogs.starting(); + root.getTree("/").getChild("test").getChild("jcr:content").getChild("n").setProperty("foo","bar2"); + root.commit(); + Assert.assertTrue(customLogs.getLogs().size() == 0); + Assert.assertFalse(customLogs.getLogs().contains("Failed to index the node [/test]")); + + } finally { + customLogs.finished(); + } + + } + + @Test + public void sameOrderablePropertyWithandWithoutFunction() throws Exception{ + LogCustomizer customLogs = LogCustomizer.forLogger(LuceneIndexEditor.class.getName()).enable(Level.WARN).create(); + // Create nodes that will be served by the index definition that follows + Tree test = root.getTree("/").addChild("test"); + test.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME); + + test.setProperty("foo", "bar"); + + root.commit(); + + // Index def with same property - ordered - one with function and one without + Tree luceneIndex = createIndex("upper", Collections.emptySet()); + Tree nonFunc = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES) + .addChild("nt:unstructured") + .addChild(FulltextIndexConstants.PROP_NODE) + .addChild("foo"); + nonFunc.setProperty(FulltextIndexConstants.PROP_ORDERED,true); + nonFunc.setProperty("name", "foo"); + + Tree func = luceneIndex.getChild(FulltextIndexConstants.INDEX_RULES) + .getChild("nt:unstructured") + .getChild(FulltextIndexConstants.PROP_NODE) + .addChild("testOak"); + func.setProperty(FulltextIndexConstants.PROP_ORDERED,true); + func.setProperty(FulltextIndexConstants.PROP_FUNCTION, "fn:upper-case(@foo)"); + + // Now do some change in the node that are covered by above index defintion + try { + customLogs.starting(); + root.getTree("/").getChild("test").setProperty("foo","bar2"); + root.commit(); + Assert.assertFalse(customLogs.getLogs().contains("Failed to index the node [/test]")); + + } finally { + customLogs.finished(); + } + + } + protected String explain(String query){ String explain = "explain " + query;