You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by am...@apache.org on 2014/10/28 07:47:04 UTC

svn commit: r1634792 - in /jackrabbit/oak/trunk/oak-lucene/src: main/java/org/apache/jackrabbit/oak/plugins/index/lucene/ test/java/org/apache/jackrabbit/oak/plugins/index/lucene/

Author: amitj
Date: Tue Oct 28 06:47:04 2014
New Revision: 1634792

URL: http://svn.apache.org/r1634792
Log:
OAK-2198 - Add support for declaringNodeTypes to only index node with specific types

Modified:
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java?rev=1634792&r1=1634791&r2=1634792&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java Tue Oct 28 06:47:04 2014
@@ -40,6 +40,7 @@ import org.apache.lucene.codecs.Codec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.ENTRY_COUNT_PROPERTY_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COUNT;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.BLOB_SIZE;
@@ -72,6 +73,8 @@ public class IndexDefinition {
 
     private final Set<String> orderedProps;
 
+    private final Set<String> declaringNodeTypes;
+
     private final boolean fullTextEnabled;
 
     private final boolean storageEnabled;
@@ -112,6 +115,8 @@ public class IndexDefinition {
         this.excludes = toLowerCase(getMultiProperty(defn, EXCLUDE_PROPERTY_NAMES));
         this.includes = getMultiProperty(defn, INCLUDE_PROPERTY_NAMES);
         this.orderedProps = getMultiProperty(defn, ORDERED_PROP_NAMES);
+        this.declaringNodeTypes = getMultiProperty(defn, DECLARING_NODE_TYPES);
+
         this.blobSize = getOptionalValue(defn, BLOB_SIZE, DEFAULT_BLOB_SIZE);
 
         this.fullTextEnabled = getOptionalValue(defn, FULL_TEXT_ENABLED, true);
@@ -169,6 +174,9 @@ public class IndexDefinition {
         return propertyTypes;
     }
 
+    public Set<String> getDeclaringNodeTypes() {
+        return declaringNodeTypes;
+    }
     /**
      * Checks if a given property should be stored in the lucene index or not
      */

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java?rev=1634792&r1=1634791&r2=1634792&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java Tue Oct 28 06:47:04 2014
@@ -21,9 +21,11 @@ package org.apache.jackrabbit.oak.plugin
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 import javax.annotation.CheckForNull;
 
+import com.google.common.collect.Sets;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.query.fulltext.FullTextExpression;
 import org.apache.jackrabbit.oak.spi.query.Filter;
@@ -88,19 +90,40 @@ public class IndexPlanner {
             //TODO Need a way to have better cost estimate to indicate that
             //this index can evaluate more propertyRestrictions natively (if more props are indexed)
             //For now we reduce cost per entry
+            int costPerEntryFactor = indexedProps.size();
+            
+            // Restrict matching index when declaringNodeTypes declared
+            Set<String> supertypes = getSuperTypes(filter);
+            if (!defn.getDeclaringNodeTypes().isEmpty()) {
+                if ((supertypes != null) && !Sets
+                    .intersection(defn.getDeclaringNodeTypes(), supertypes).isEmpty()) {
+                    // Reduce cost per entry by a small factor because number of nodes would be less
+                    costPerEntryFactor += 1;
+                } else {
+                    return null;
+                }
+            }
+            //this index can evaluate more propertyRestrictions natively (if more props are indexed)
+            //For now we reduce cost per entry
             IndexPlan.Builder plan = defaultPlan();
             if (plan != null) {
-                return plan.setCostPerEntry(1.0 / indexedProps.size());
+                return plan.setCostPerEntry(1.0 / costPerEntryFactor);
             }
         }
 
         //TODO Support for path restrictions
-        //TODO support for NodeTypes
         //TODO Support for property existence queries
         //TODO support for nodeName queries
         return null;
     }
 
+    private static Set<String> getSuperTypes(Filter filter) {
+        if (filter != null && !filter.matchesAllTypes()) {
+            return filter.getSupertypes();
+        }
+        return null;
+    }
+
     private IndexPlan.Builder defaultPlan() {
         return new IndexPlan.Builder()
                 .setCostPerExecution(1) // we're local. Low-cost

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java?rev=1634792&r1=1634791&r2=1634792&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java Tue Oct 28 06:47:04 2014
@@ -36,6 +36,7 @@ import org.apache.jackrabbit.oak.api.Pro
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexEditor;
 import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
 import org.apache.jackrabbit.oak.spi.commit.Editor;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -81,13 +82,21 @@ public class LuceneIndexEditor implement
 
     private boolean propertiesChanged = false;
 
-    LuceneIndexEditor(NodeBuilder definition, Analyzer analyzer,
-            IndexUpdateCallback updateCallback) throws CommitFailedException {
+    private NodeState root;
+
+    private TypePredicate typePredicate;
+
+    LuceneIndexEditor(NodeState root, NodeBuilder definition, Analyzer analyzer,
+        IndexUpdateCallback updateCallback) throws CommitFailedException {
         this.parent = null;
         this.name = null;
         this.path = "/";
         this.context = new LuceneIndexEditorContext(definition, analyzer,
                 updateCallback);
+        this.root = root;
+        if (root != null && !context.getDefinition().getDeclaringNodeTypes().isEmpty()) {
+            typePredicate = new TypePredicate(root, context.getDefinition().getDeclaringNodeTypes());
+        }
     }
 
     private LuceneIndexEditor(LuceneIndexEditor parent, String name) {
@@ -95,6 +104,8 @@ public class LuceneIndexEditor implement
         this.name = name;
         this.path = null;
         this.context = parent.context;
+        this.root = parent.root;
+        this.typePredicate = parent.typePredicate;
     }
 
     public String getPath() {
@@ -200,6 +211,11 @@ public class LuceneIndexEditor implement
         //TODO Possibly we can add support for compound properties like foo/bar
         //i.e. support for relative path restrictions
 
+        // Check for declaringNodeType validity
+        if (typePredicate != null && !typePredicate.apply(state)) {
+            return null;
+        }
+
         List<Field> fields = new ArrayList<Field>();
         boolean dirty = false;
         for (PropertyState property : state.getProperties()) {

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java?rev=1634792&r1=1634791&r2=1634792&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java Tue Oct 28 06:47:04 2014
@@ -51,7 +51,7 @@ public class LuceneIndexEditorProvider i
             String type, NodeBuilder definition, NodeState root, IndexUpdateCallback callback)
             throws CommitFailedException {
         if (TYPE_LUCENE.equals(type)) {
-            return new LuceneIndexEditor(definition, analyzer, callback);
+            return new LuceneIndexEditor(root, definition, analyzer, callback);
         }
         return null;
     }

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1634792&r1=1634791&r2=1634792&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java Tue Oct 28 06:47:04 2014
@@ -29,6 +29,7 @@ import java.util.Set;
 import javax.jcr.PropertyType;
 
 import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.Oak;
@@ -118,6 +119,7 @@ public class LucenePropertyIndexTest ext
     @Test
     public void indexSelectionVsNodeType() throws Exception {
         Tree luceneIndex = createIndex("test1", of("propa"));
+        // decrease cost of lucene property index
         luceneIndex.setProperty(IndexConstants.ENTRY_COUNT_PROPERTY_NAME, 5L, Type.LONG);
 
         // Decrease cost of node type index
@@ -138,13 +140,79 @@ public class LucenePropertyIndexTest ext
         root.commit();
 
         String propaQuery = "select [jcr:path] from [nt:unstructured] where [propa] = 'foo'";
-        String explain = explain(propaQuery);
         assertThat(explain(propaQuery), containsString("lucene:test1"));
 
         assertQuery(propaQuery, paths);
     }
 
     @Test
+    public void declaringNodeTypeSameProp() throws Exception {
+        createIndex("test1", of("propa"));
+
+        Tree indexWithType = createIndex("test2", of("propa"));
+        indexWithType.setProperty(PropertyStates
+            .createProperty(IndexConstants.DECLARING_NODE_TYPES, of("nt:unstructured"),
+                Type.STRINGS));
+
+        Tree test = root.getTree("/").addChild("test");
+        test.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+        root.commit();
+
+        Tree a = test.addChild("a");
+        a.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+        a.setProperty("propa", "foo");
+        Tree b = test.addChild("b");
+        b.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+        b.setProperty("propa", "foo");
+
+        test.addChild("c").setProperty("propa", "foo");
+        test.addChild("d").setProperty("propa", "foo");
+
+        root.commit();
+
+        String propabQuery = "select [jcr:path] from [nt:unstructured] where [propa] = 'foo'";
+        assertThat(explain(propabQuery), containsString("lucene:test2"));
+        assertQuery(propabQuery, asList("/test/a", "/test/b"));
+
+        String propcdQuery = "select [jcr:path] from [nt:base] where [propa] = 'foo'";
+        assertThat(explain(propcdQuery), containsString("lucene:test1"));
+        assertQuery(propcdQuery, asList("/test/a", "/test/b", "/test/c", "/test/d"));
+    }
+
+    @Test
+    public void declaringNodeTypeSingleIndex() throws Exception {
+        Tree indexWithType = createIndex("test2", of("propa", "propb"));
+        indexWithType.setProperty(PropertyStates
+            .createProperty(IndexConstants.DECLARING_NODE_TYPES, of("nt:unstructured"),
+                Type.STRINGS));
+
+        Tree test = root.getTree("/").addChild("test");
+        test.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+        root.commit();
+
+        Tree a = test.addChild("a");
+        a.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+        a.setProperty("propa", "foo");
+        a.setProperty("propb", "baz");
+
+        Tree b = test.addChild("b");
+        b.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+        b.setProperty("propa", "foo");
+        b.setProperty("propb", "baz");
+
+        root.commit();
+
+        String propabQuery = "select [jcr:path] from [nt:unstructured] where [propb] = 'baz' and " +
+            "[propa] = 'foo'";
+        assertThat(explain(propabQuery), containsString("lucene:test2"));
+        assertQuery(propabQuery, asList("/test/a", "/test/b"));
+
+        String propNoIdxQuery = "select [jcr:path] from [nt:base] where [propb] = 'baz'";
+        assertThat(explain(propNoIdxQuery), containsString("no-index"));
+        assertQuery(propNoIdxQuery, ImmutableList.<String>of());
+    }
+
+    @Test
     public void rangeQueriesWithLong() throws Exception {
         Tree idx = createIndex("test1", of("propa", "propb"));
         Tree propIdx = idx.addChild(PROP_NODE).addChild("propa");