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 ch...@apache.org on 2014/10/31 07:32:56 UTC

svn commit: r1635689 - in /jackrabbit/oak/branches/1.0: ./ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/ oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/

Author: chetanm
Date: Fri Oct 31 06:32:56 2014
New Revision: 1635689

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

Merging 1634792,1634814

Modified:
    jackrabbit/oak/branches/1.0/   (props changed)
    jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
    jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
    jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
    jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java
    jackrabbit/oak/branches/1.0/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java

Propchange: jackrabbit/oak/branches/1.0/
------------------------------------------------------------------------------
  Merged /jackrabbit/oak/trunk:r1634792,1634814

Modified: jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java?rev=1635689&r1=1635688&r2=1635689&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java Fri Oct 31 06:32:56 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,13 @@ public class IndexDefinition {
         return propertyTypes;
     }
 
+    public Set<String> getDeclaringNodeTypes() {
+        return declaringNodeTypes;
+    }
+
+    public boolean hasDeclaredNodeTypes(){
+        return !declaringNodeTypes.isEmpty();
+    }
     /**
      * Checks if a given property should be stored in the lucene index or not
      */

Modified: jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java?rev=1635689&r1=1635688&r2=1635689&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java Fri Oct 31 06:32:56 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,39 @@ 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
+            if (defn.hasDeclaredNodeTypes()) {
+                if (supportsNodeTypes(filter)) {
+                    // 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;
     }
 
+    /**
+     * Determines if NodeTypes as defined in Filter are supported by current index
+     */
+    private boolean supportsNodeTypes(Filter filter) {
+        return !Sets
+            .intersection(defn.getDeclaringNodeTypes(), getSuperTypes(filter)).isEmpty();
+    }
+
     private IndexPlan.Builder defaultPlan() {
         return new IndexPlan.Builder()
                 .setCostPerExecution(1) // we're local. Low-cost
@@ -149,4 +171,8 @@ public class IndexPlanner {
         }
         return orderEntries;
     }
+
+    private static Set<String> getSuperTypes(Filter filter) {
+        return filter.matchesAllTypes() ? Collections.<String>emptySet() : filter.getSupertypes();
+    }
 }

Modified: jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java?rev=1635689&r1=1635688&r2=1635689&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java Fri Oct 31 06:32:56 2014
@@ -29,6 +29,8 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -36,6 +38,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 +84,23 @@ public class LuceneIndexEditor implement
 
     private boolean propertiesChanged = false;
 
-    LuceneIndexEditor(NodeBuilder definition, Analyzer analyzer,
-            IndexUpdateCallback updateCallback) throws CommitFailedException {
+    private NodeState root;
+
+    private final Predicate 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 (context.getDefinition().hasDeclaredNodeTypes()) {
+            typePredicate = new TypePredicate(root, context.getDefinition().getDeclaringNodeTypes());
+        } else {
+            typePredicate = Predicates.alwaysTrue();
+        }
     }
 
     private LuceneIndexEditor(LuceneIndexEditor parent, String name) {
@@ -95,6 +108,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 +215,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.apply(state)) {
+            return null;
+        }
+
         List<Field> fields = new ArrayList<Field>();
         boolean dirty = false;
         for (PropertyState property : state.getProperties()) {

Modified: jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java?rev=1635689&r1=1635688&r2=1635689&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorProvider.java Fri Oct 31 06:32:56 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/branches/1.0/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1635689&r1=1635688&r2=1635689&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java Fri Oct 31 06:32:56 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");