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 to...@apache.org on 2014/07/30 17:39:59 UTC

svn commit: r1614689 - in /jackrabbit/oak/trunk/oak-solr-core/src: main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/ main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/ main/java/org/apache/jackrabbit/oak/plugins/index/sol...

Author: tommaso
Date: Wed Jul 30 15:39:58 2014
New Revision: 1614689

URL: http://svn.apache.org/r1614689
Log:
OAK-1609 - added property exclusion for Solr indexing/searching

Added:
    jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditorTest.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfiguration.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrNodeStateConfiguration.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/SolrServerConfigurationDefaults.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/package-info.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/osgi/OakSolrConfigurationProviderService.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
    jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml
    jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndexTest.java
    jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java Wed Jul 30 15:39:58 2014
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.solr.configuration;
 
+import java.util.Arrays;
+import java.util.Collection;
+
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 
@@ -24,6 +27,8 @@ import org.apache.jackrabbit.oak.spi.que
  */
 public class DefaultSolrConfiguration implements OakSolrConfiguration {
 
+    private static Collection<String> ignoredProperties = Arrays.asList(SolrServerConfigurationDefaults.IGNORED_PROPERTIES.split(","));
+
     @Override
     public String getFieldNameFor(Type<?> propertyType) {
         if (Type.BINARIES.equals(propertyType) || Type.BINARY.equals(propertyType)) {
@@ -102,4 +107,9 @@ public class DefaultSolrConfiguration im
         return SolrServerConfigurationDefaults.PATH_RESTRICTIONS;
     }
 
+    @Override
+    public Collection<String> getIgnoredProperties() {
+        return ignoredProperties;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfiguration.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfiguration.java Wed Jul 30 15:39:58 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.solr.configuration;
 
+import java.util.Collection;
+
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 
@@ -100,4 +102,11 @@ public interface OakSolrConfiguration {
      * for filtering by {@link org.apache.jackrabbit.oak.spi.query.Filter.PathRestriction}s
      */
     boolean useForPathRestrictions();
+
+    /**
+     * Provide the collection of properties that should be neither indexed nor searched by the Solr index
+     *
+     * @return a <code>Collection</code> of <code>String</code>s representing the names of the ignored properties
+     */
+    Collection<String> getIgnoredProperties();
 }

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrNodeStateConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrNodeStateConfiguration.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrNodeStateConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrNodeStateConfiguration.java Wed Jul 30 15:39:58 2014
@@ -16,6 +16,10 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.solr.configuration;
 
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.solr.server.EmbeddedSolrServerProvider;
@@ -27,7 +31,7 @@ import org.apache.jackrabbit.oak.spi.sta
  * For each of the supported properties a default is provided if either the
  * property doesn't exist in the node or if the value is <code>null</code> or
  * empty <code>String</code>.
- * <p>
+ * <p/>
  * Subclasses of this should at least provide the {@link org.apache.jackrabbit.oak.spi.state.NodeState} which holds
  * the configuration.
  */
@@ -119,6 +123,18 @@ public abstract class OakSolrNodeStateCo
         return getBooleanValueFor(Properties.PATH_RESTRICTIONS, SolrServerConfigurationDefaults.PATH_RESTRICTIONS);
     }
 
+    @Override
+    public Collection<String> getIgnoredProperties() {
+        Collection<String> ignoredProperties;
+        String ignoredPropertiesString = getStringValueFor(Properties.IGNORED_PROPERTIES, SolrServerConfigurationDefaults.IGNORED_PROPERTIES);
+        if (ignoredPropertiesString != null) {
+            ignoredProperties = Arrays.asList(ignoredPropertiesString.split(","));
+        } else {
+            ignoredProperties = Collections.emptyList();
+        }
+        return ignoredProperties;
+    }
+
     private boolean getBooleanValueFor(String propertyName, boolean defaultValue) {
         boolean value = defaultValue;
         NodeState configurationNodeState = getConfigurationNodeState();
@@ -143,7 +159,7 @@ public abstract class OakSolrNodeStateCo
         return (int) value;
     }
 
-    protected String getStringValueFor(String propertyName, String defaultValue) {
+    private String getStringValueFor(String propertyName, String defaultValue) {
         String value = defaultValue;
         NodeState configurationNodeState = getConfigurationNodeState();
         if (configurationNodeState.exists()) {
@@ -187,5 +203,6 @@ public abstract class OakSolrNodeStateCo
         public static final String PROPERTY_RESTRICIONS = "propertyRestrictions";
         public static final String PRIMARY_TYPES = "primaryTypes";
         public static final String PATH_RESTRICTIONS = "pathRestrictions";
+        public static final String IGNORED_PROPERTIES = "ignoredProperties";
     }
 }

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/SolrServerConfigurationDefaults.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/SolrServerConfigurationDefaults.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/SolrServerConfigurationDefaults.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/SolrServerConfigurationDefaults.java Wed Jul 30 15:39:58 2014
@@ -40,4 +40,5 @@ public class SolrServerConfigurationDefa
     public static final boolean PROPERTY_RESTRICTIONS = false;
     public static final boolean PATH_RESTRICTIONS = false;
     public static final boolean PRIMARY_TYPES = false;
+    public static final String IGNORED_PROPERTIES = "";
 }

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/package-info.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/package-info.java Wed Jul 30 15:39:58 2014
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.1")
+@Version("1.2")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.plugins.index.solr.configuration;
 

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditor.java Wed Jul 30 15:39:58 2014
@@ -212,19 +212,21 @@ public class SolrIndexEditor implements 
         inputDocument.addField(configuration.getPathField(), path);
         for (PropertyState property : state.getProperties()) {
             // try to get the field to use for this property from configuration
-            String fieldName = configuration.getFieldNameFor(property.getType());
-            if (fieldName != null) {
-                inputDocument.addField(
-                        fieldName, property.getValue(property.getType()));
-            } else {
-                // or fallback to adding propertyName:stringValue(s)
-                if (property.isArray()) {
-                    for (String s : property.getValue(Type.STRINGS)) {
-                        inputDocument.addField(property.getName(), s);
-                    }
-                } else {
+            if (!configuration.getIgnoredProperties().contains(property.getName())) {
+                String fieldName = configuration.getFieldNameFor(property.getType());
+                if (fieldName != null) {
                     inputDocument.addField(
-                            property.getName(), property.getValue(Type.STRING));
+                            fieldName, property.getValue(property.getType()));
+                } else {
+                    // or fallback to adding propertyName:stringValue(s)
+                    if (property.isArray()) {
+                        for (String s : property.getValue(Type.STRINGS)) {
+                            inputDocument.addField(property.getName(), s);
+                        }
+                    } else {
+                        inputDocument.addField(
+                                property.getName(), property.getValue(Type.STRING));
+                    }
                 }
             }
         }

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/osgi/OakSolrConfigurationProviderService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/osgi/OakSolrConfigurationProviderService.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/osgi/OakSolrConfigurationProviderService.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/osgi/OakSolrConfigurationProviderService.java Wed Jul 30 15:39:58 2014
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.solr.osgi;
 
+import java.util.Arrays;
+import java.util.Collection;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Property;
@@ -36,29 +39,19 @@ import org.osgi.service.component.Compon
 @Service(OakSolrConfigurationProvider.class)
 public class OakSolrConfigurationProviderService implements OakSolrConfigurationProvider {
 
-    private static final String DEFAULT_DESC_FIELD = SolrServerConfigurationDefaults.DESC_FIELD_NAME;
-    private static final String DEFAULT_CHILD_FIELD = SolrServerConfigurationDefaults.CHILD_FIELD_NAME;
-    private static final String DEFAULT_PARENT_FIELD = SolrServerConfigurationDefaults.ANC_FIELD_NAME;
-    private static final String DEFAULT_PATH_FIELD = SolrServerConfigurationDefaults.PATH_FIELD_NAME;
-    private static final String DEFAULT_CATCHALL_FIELD = SolrServerConfigurationDefaults.CATCHALL_FIELD;
-    private static final int DEFAULT_ROWS = SolrServerConfigurationDefaults.ROWS;
-    private static final boolean DEFAULT_PATH_RESTRICTIONS = SolrServerConfigurationDefaults.PATH_RESTRICTIONS;
-    private static final boolean DEFAULT_PROPERTY_RESTRICTIONS = SolrServerConfigurationDefaults.PROPERTY_RESTRICTIONS;
-    private static final boolean DEFAULT_PRIMARY_TYPES_RESTRICTIONS = SolrServerConfigurationDefaults.PRIMARY_TYPES;
-
-    @Property(value = DEFAULT_DESC_FIELD, label = "field for descendants search")
+    @Property(value = SolrServerConfigurationDefaults.DESC_FIELD_NAME, label = "field for descendants search")
     private static final String PATH_DESCENDANTS_FIELD = "path.desc.field";
 
-    @Property(value = DEFAULT_CHILD_FIELD, label = "field for children search")
+    @Property(value = SolrServerConfigurationDefaults.CHILD_FIELD_NAME, label = "field for children search")
     private static final String PATH_CHILDREN_FIELD = "path.child.field";
 
-    @Property(value = DEFAULT_PARENT_FIELD, label = "field for parent search")
+    @Property(value = SolrServerConfigurationDefaults.ANC_FIELD_NAME, label = "field for parent search")
     private static final String PATH_PARENT_FIELD = "path.parent.field";
 
-    @Property(value = DEFAULT_PATH_FIELD, label = "field for path search")
+    @Property(value = SolrServerConfigurationDefaults.PATH_FIELD_NAME, label = "field for path search")
     private static final String PATH_EXACT_FIELD = "path.exact.field";
 
-    @Property(value = DEFAULT_CATCHALL_FIELD,label = "catch all field")
+    @Property(value = SolrServerConfigurationDefaults.CATCHALL_FIELD,label = "catch all field")
     private static final String CATCH_ALL_FIELD = "catch.all.field";
 
     @Property(options = {
@@ -76,19 +69,22 @@ public class OakSolrConfigurationProvide
     private static final String COMMIT_POLICY = "commit.policy";
 
 
-    @Property(intValue = DEFAULT_ROWS, label = "rows")
+    @Property(intValue = SolrServerConfigurationDefaults.ROWS, label = "rows")
     private static final String ROWS = "rows";
 
 
-    @Property(boolValue = DEFAULT_PATH_RESTRICTIONS, label = "path restrictions")
+    @Property(boolValue = SolrServerConfigurationDefaults.PATH_RESTRICTIONS, label = "path restrictions")
     private static final String PATH_RESTRICTIONS = "path.restrictions";
 
-    @Property(boolValue = DEFAULT_PROPERTY_RESTRICTIONS, label = "property restrictions")
+    @Property(boolValue = SolrServerConfigurationDefaults.PROPERTY_RESTRICTIONS, label = "property restrictions")
     private static final String PROPERTY_RESTRICTIONS = "property.restrictions";
 
-    @Property(boolValue = DEFAULT_PRIMARY_TYPES_RESTRICTIONS, label = "primary types restrictions")
+    @Property(boolValue = SolrServerConfigurationDefaults.PRIMARY_TYPES, label = "primary types restrictions")
     private static final String PRIMARY_TYPES_RESTRICTIONS = "primarytypes.restrictions";
 
+    @Property(value = SolrServerConfigurationDefaults.IGNORED_PROPERTIES, label = "ignored properties")
+    private static final String IGNORED_PROPERTIES = "ignored.properties";
+
     private String pathChildrenFieldName;
     private String pathParentFieldName;
     private String pathDescendantsFieldName;
@@ -99,6 +95,7 @@ public class OakSolrConfigurationProvide
     private boolean useForPathRestrictions;
     private boolean useForPropertyRestrictions;
     private boolean useForPrimaryTypes;
+    private Collection<String> ignoredProperties;
 
     private OakSolrConfiguration oakSolrConfiguration;
 
@@ -115,6 +112,7 @@ public class OakSolrConfigurationProvide
         useForPathRestrictions = Boolean.valueOf(String.valueOf(componentContext.getProperties().get(PATH_RESTRICTIONS)));
         useForPropertyRestrictions = Boolean.valueOf(String.valueOf(componentContext.getProperties().get(PROPERTY_RESTRICTIONS)));
         useForPrimaryTypes = Boolean.valueOf(String.valueOf(componentContext.getProperties().get(PRIMARY_TYPES_RESTRICTIONS)));
+        ignoredProperties = Arrays.asList(String.valueOf(componentContext.getProperties().get(IGNORED_PROPERTIES)).split(","));
     }
 
     @Override
@@ -186,6 +184,11 @@ public class OakSolrConfigurationProvide
                 public boolean useForPathRestrictions() {
                     return useForPathRestrictions;
                 }
+
+                @Override
+                public Collection<String> getIgnoredProperties() {
+                    return ignoredProperties;
+                }
             };
         }
         return oakSolrConfiguration;

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java Wed Jul 30 15:39:58 2014
@@ -120,13 +120,22 @@ public class SolrQueryIndex implements F
         // property restriction OR native language property restriction defined AND property restriction handled
         if (filter.getPropertyRestrictions() != null && filter.getPropertyRestrictions().size() > 0
                 && (filter.getPropertyRestriction(NATIVE_SOLR_QUERY) != null || filter.getPropertyRestriction(NATIVE_LUCENE_QUERY) != null
-                || configuration.useForPropertyRestrictions())) {
+                || configuration.useForPropertyRestrictions()) && !hasIgnoredProperties(filter.getPropertyRestrictions())) {
             match++;
         }
 
         return match;
     }
 
+    private boolean hasIgnoredProperties(Collection<Filter.PropertyRestriction> propertyRestrictions) {
+        for (Filter.PropertyRestriction pr : propertyRestrictions) {
+            if (configuration.getIgnoredProperties().contains(pr.propertyName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public String getPlan(Filter filter, NodeState nodeState) {
         return getQuery(filter).toString();
@@ -195,8 +204,11 @@ public class SolrQueryIndex implements F
                         queryBuilder.append(nativeQueryString);
                     }
                 } else {
-                    if (!configuration.useForPropertyRestrictions() || pr.propertyName.contains("/") ||
-                            "rep:excerpt".equals(pr.propertyName)) {
+                    if (!configuration.useForPropertyRestrictions() // Solr index not used for properties
+                            || pr.propertyName.contains("/") // no child-level property restrictions
+                            || "rep:excerpt".equals(pr.propertyName) // rep:excerpt is handled by the query engine
+                            || configuration.getIgnoredProperties().contains(pr.propertyName) // property is explicitly ignored
+                            ) {
                         continue;
                     }
 

Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml Wed Jul 30 15:39:58 2014
@@ -16,101 +16,107 @@
  limitations under the License.
 -->
 <schema name="minimal" version="1.5">
-  <types>
-    <fieldType name="string" class="solr.StrField"/>
-    <fieldType name="descendent_path" class="solr.TextField">
-      <analyzer type="index">
-        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
-        <filter class="solr.PatternCaptureGroupFilterFactory" pattern="((/).*)" preserve_original="false"/>
-        <filter class="solr.RemoveDuplicatesTokenFilterFactory" />
-      </analyzer>
-      <analyzer type="query">
-        <tokenizer class="solr.KeywordTokenizerFactory" />
-      </analyzer>
-    </fieldType>
-    <fieldType name="children_path" class="solr.TextField">
-      <analyzer type="index">
-        <tokenizer class="solr.KeywordTokenizerFactory"/>
-        <filter class="solr.ReverseStringFilterFactory" />
-        <filter class="solr.LengthFilterFactory" min="2" max="2147483647"/>
-        <filter class="solr.PatternReplaceFilterFactory" pattern="([^\/]+)(\/)" replacement="$2" replace="first"/>
-        <filter class="solr.PatternReplaceFilterFactory" pattern="(\/)(.+)" replacement="$2" replace="first"/>
-        <filter class="solr.ReverseStringFilterFactory" />
-      </analyzer>
-      <analyzer type="query">
-        <tokenizer class="solr.KeywordTokenizerFactory" />
-      </analyzer>
-    </fieldType>
-    <fieldType name="parent_path" class="solr.TextField">
-      <analyzer type="index">
-        <tokenizer class="solr.KeywordTokenizerFactory" />
-      </analyzer>
-      <analyzer type="query">
-        <tokenizer class="solr.KeywordTokenizerFactory"/>
-        <filter class="solr.ReverseStringFilterFactory" />
-        <filter class="solr.PatternReplaceFilterFactory" pattern="[^\/]+\/" replacement="" replace="first"/>
-        <filter class="solr.ReverseStringFilterFactory" />
-      </analyzer>
-    </fieldType>
-    <fieldType name="text_keepcase" class="solr.TextField" positionIncrementGap="100">
-      <analyzer type="index">
-        <tokenizer class="solr.StandardTokenizerFactory"/>
-      </analyzer>
-      <analyzer type="query">
-        <tokenizer class="solr.StandardTokenizerFactory"/>
-      </analyzer>
-    </fieldType>
-    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
-      <analyzer type="index">
-        <tokenizer class="solr.StandardTokenizerFactory"/>
-        <filter class="solr.LowerCaseFilterFactory"/>
-      </analyzer>
-      <analyzer type="query">
-        <tokenizer class="solr.StandardTokenizerFactory"/>
-        <filter class="solr.LowerCaseFilterFactory"/>
-      </analyzer>
-    </fieldType>
-
-    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
-
-    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
-    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
-    <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
-    <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
-    <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
-    <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
-    <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
-
-    <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
-
-    <fieldtype name="binary" class="solr.BinaryField"/>
-
-    <fieldType name="pint" class="solr.IntField"/>
-    <fieldType name="plong" class="solr.LongField"/>
-    <fieldType name="pfloat" class="solr.FloatField"/>
-    <fieldType name="pdouble" class="solr.DoubleField"/>
-    <fieldType name="pdate" class="solr.DateField" sortMissingLast="true"/>
-
-    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
-    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField"/>
-  </types>
-  <fields>
-    <field name="path_exact" type="string" indexed="true" stored="true"/>
-    <field name="path_child" type="children_path" indexed="true" stored="false"/>
-    <field name="path_anc" type="parent_path" indexed="true" stored="false"/>
-    <field name="path_des" type="descendent_path" indexed="true" stored="false"/>
-    <field name="catch_all" type="text_general" indexed="true" stored="false" multiValued="true"/>
-    <field name=":path" type="string" indexed="true" stored="false"/>
-    <field name="_version_" type="long" indexed="true" stored="true"/>
-    <dynamicField name="*" type="text_general" indexed="true" stored="true" multiValued="true"/>
-  </fields>
-  <uniqueKey>path_exact</uniqueKey>
-  <copyField source="path_exact" dest="path_anc"/>
-  <copyField source="path_exact" dest="path_des"/>
-  <copyField source="path_exact" dest="path_child"/>
-  <copyField source="path_exact" dest=":path"/>
-  <copyField source="*" dest="catch_all"/>
+    <types>
+        <fieldType name="string" class="solr.StrField"/>
+        <fieldType name="descendent_path" class="solr.TextField">
+            <analyzer type="index">
+                <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/"/>
+                <filter class="solr.PatternCaptureGroupFilterFactory" pattern="((/).*)" preserve_original="false"/>
+                <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+            </analyzer>
+            <analyzer type="query">
+                <tokenizer class="solr.KeywordTokenizerFactory"/>
+            </analyzer>
+        </fieldType>
+        <fieldType name="children_path" class="solr.TextField">
+            <analyzer type="index">
+                <tokenizer class="solr.KeywordTokenizerFactory"/>
+                <filter class="solr.ReverseStringFilterFactory"/>
+                <filter class="solr.LengthFilterFactory" min="2" max="2147483647"/>
+                <filter class="solr.PatternReplaceFilterFactory" pattern="([^\/]+)(\/)" replacement="$2"
+                        replace="first"/>
+                <filter class="solr.PatternReplaceFilterFactory" pattern="(\/)(.+)" replacement="$2" replace="first"/>
+                <filter class="solr.ReverseStringFilterFactory"/>
+            </analyzer>
+            <analyzer type="query">
+                <tokenizer class="solr.KeywordTokenizerFactory"/>
+            </analyzer>
+        </fieldType>
+        <fieldType name="parent_path" class="solr.TextField">
+            <analyzer type="index">
+                <tokenizer class="solr.KeywordTokenizerFactory"/>
+            </analyzer>
+            <analyzer type="query">
+                <tokenizer class="solr.KeywordTokenizerFactory"/>
+                <filter class="solr.ReverseStringFilterFactory"/>
+                <filter class="solr.PatternReplaceFilterFactory" pattern="[^\/]+\/" replacement="" replace="first"/>
+                <filter class="solr.ReverseStringFilterFactory"/>
+            </analyzer>
+        </fieldType>
+        <fieldType name="text_keepcase" class="solr.TextField" positionIncrementGap="100">
+            <analyzer type="index">
+                <tokenizer class="solr.StandardTokenizerFactory"/>
+            </analyzer>
+            <analyzer type="query">
+                <tokenizer class="solr.StandardTokenizerFactory"/>
+            </analyzer>
+        </fieldType>
+        <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
+            <analyzer type="index">
+                <tokenizer class="solr.ClassicTokenizerFactory" maxTokenLength="100000"/>
+                <filter class="solr.LowerCaseFilterFactory"/>
+            </analyzer>
+            <analyzer type="query">
+                <tokenizer class="solr.ClassicTokenizerFactory" maxTokenLength="100000"/>
+                <filter class="solr.LowerCaseFilterFactory"/>
+            </analyzer>
+        </fieldType>
+
+        <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
+
+        <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
+        <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
+        <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+        <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
+
+        <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
+        <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
+        <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
+        <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+        <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
+
+        <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
+
+        <fieldtype name="binary" class="solr.BinaryField"/>
+
+        <fieldType name="pint" class="solr.IntField"/>
+        <fieldType name="plong" class="solr.LongField"/>
+        <fieldType name="pfloat" class="solr.FloatField"/>
+        <fieldType name="pdouble" class="solr.DoubleField"/>
+        <fieldType name="pdate" class="solr.DateField" sortMissingLast="true"/>
+
+        <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD"
+                   currencyConfig="currency.xml"/>
+        <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField"/>
+    </types>
+    <fields>
+        <field name="path_exact" type="string" indexed="true" stored="true"/>
+        <field name="path_child" type="children_path" indexed="true" stored="false"/>
+        <field name="path_anc" type="parent_path" indexed="true" stored="false"/>
+        <field name="path_des" type="descendent_path" indexed="true" stored="false"/>
+        <field name="catch_all" type="text_general" indexed="true" stored="false" multiValued="true"/>
+        <field name=":path" type="string" indexed="true" stored="false"/>
+        <field name="_version_" type="long" indexed="true" stored="true"/>
+
+        <field name="rep:members" type="string" indexed="true" stored="true" multiValued="true"/>
+        <field name="rep:principalName" type="string" indexed="true" stored="true" multiValued="true"/>
+        <dynamicField name="*_bin" type="string" indexed="true" stored="true" multiValued="true"/>
+        <dynamicField name="*" type="text_general" indexed="true" stored="true" multiValued="true"/>
+    </fields>
+    <uniqueKey>path_exact</uniqueKey>
+    <copyField source="path_exact" dest="path_anc"/>
+    <copyField source="path_exact" dest="path_des"/>
+    <copyField source="path_exact" dest="path_child"/>
+    <copyField source="path_exact" dest=":path"/>
+    <copyField source="*" dest="catch_all"/>
 </schema>

Added: jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditorTest.java?rev=1614689&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditorTest.java (added)
+++ jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditorTest.java Wed Jul 30 15:39:58 2014
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.index.solr.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
+import org.apache.jackrabbit.oak.plugins.index.solr.TestUtils;
+import org.apache.jackrabbit.oak.plugins.index.solr.configuration.DefaultSolrConfiguration;
+import org.apache.jackrabbit.oak.plugins.index.solr.configuration.OakSolrConfiguration;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Testcase for {@link org.apache.jackrabbit.oak.plugins.index.solr.index.SolrIndexEditor}
+ */
+public class SolrIndexEditorTest {
+
+    @Test
+    public void testIndexedProperties() throws Exception {
+        NodeBuilder builder = mock(NodeBuilder.class);
+        SolrServer solrServer = TestUtils.createSolrServer();
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration();
+        IndexUpdateCallback callback = mock(IndexUpdateCallback.class);
+        SolrIndexEditor solrIndexEditor = new SolrIndexEditor(builder, solrServer, configuration, callback);
+        NodeState before = mock(NodeState.class);
+        NodeState after = mock(NodeState.class);
+        Iterable properties = new Iterable<PropertyState>() {
+            @Override
+            public Iterator<PropertyState> iterator() {
+                return Arrays.asList(PropertyStates.createProperty("foo", "bar")).iterator();
+            }
+        };
+        when(after.getProperties()).thenReturn(properties);
+        solrIndexEditor.leave(before, after);
+        QueryResponse queryResponse = solrServer.query(new SolrQuery("foo:*"));
+        assertEquals(1, queryResponse.getResults().getNumFound());
+    }
+
+    @Test
+    public void testIgnoredPropertiesNotIndexed() throws Exception {
+        NodeBuilder builder = mock(NodeBuilder.class);
+        SolrServer solrServer = TestUtils.createSolrServer();
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration() {
+            @Override
+            public Collection<String> getIgnoredProperties() {
+                return Arrays.asList("foo");
+            }
+        };
+        IndexUpdateCallback callback = mock(IndexUpdateCallback.class);
+        SolrIndexEditor solrIndexEditor = new SolrIndexEditor(builder, solrServer, configuration, callback);
+        NodeState before = mock(NodeState.class);
+        NodeState after = mock(NodeState.class);
+        Iterable properties = new Iterable<PropertyState>() {
+            @Override
+            public Iterator<PropertyState> iterator() {
+                return Arrays.asList(PropertyStates.createProperty("foo", "bar")).iterator();
+            }
+        };
+        when(after.getProperties()).thenReturn(properties);
+        solrIndexEditor.leave(before, after);
+        QueryResponse queryResponse = solrServer.query(new SolrQuery("foo:*"));
+        assertEquals(0, queryResponse.getResults().getNumFound());
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/index/SolrIndexEditorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndexTest.java?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndexTest.java Wed Jul 30 15:39:58 2014
@@ -16,20 +16,27 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.solr.query;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 
+import org.apache.jackrabbit.oak.plugins.index.solr.TestUtils;
 import org.apache.jackrabbit.oak.plugins.index.solr.configuration.DefaultSolrConfiguration;
 import org.apache.jackrabbit.oak.plugins.index.solr.configuration.OakSolrConfiguration;
 import org.apache.jackrabbit.oak.query.QueryEngineSettings;
 import org.apache.jackrabbit.oak.query.ast.Operator;
 import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.query.Cursor;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.common.SolrInputDocument;
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
@@ -77,7 +84,7 @@ public class SolrQueryIndexTest {
         SelectorImpl selector = new SelectorImpl(root, "a");
 
         SolrServer solrServer = mock(SolrServer.class);
-        OakSolrConfiguration configuration = new DefaultSolrConfiguration(){
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration() {
             @Override
             public boolean useForPathRestrictions() {
                 return true;
@@ -114,7 +121,7 @@ public class SolrQueryIndexTest {
         SelectorImpl selector = new SelectorImpl(root, "a");
 
         SolrServer solrServer = mock(SolrServer.class);
-        OakSolrConfiguration configuration = new DefaultSolrConfiguration(){
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration() {
             @Override
             public boolean useForPropertyRestrictions() {
                 return true;
@@ -151,7 +158,7 @@ public class SolrQueryIndexTest {
         SelectorImpl selector = new SelectorImpl(root, "a");
 
         SolrServer solrServer = mock(SolrServer.class);
-        OakSolrConfiguration configuration = new DefaultSolrConfiguration(){
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration() {
             @Override
             public boolean useForPrimaryTypes() {
                 return true;
@@ -164,4 +171,89 @@ public class SolrQueryIndexTest {
         double cost = solrQueryIndex.getCost(filter, root);
         assertTrue(10 == cost);
     }
+
+    @Test
+    public void testCostWithPropertyRestrictionsEnabledButPropertyIgnored() throws Exception {
+        NodeState root = mock(NodeState.class);
+        when(root.getNames(any(String.class))).thenReturn(Collections.<String>emptySet());
+        SelectorImpl selector = new SelectorImpl(root, "a");
+
+        SolrServer solrServer = mock(SolrServer.class);
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration() {
+            @Override
+            public boolean useForPropertyRestrictions() {
+                return true;
+            }
+
+            @Override
+            public Collection<String> getIgnoredProperties() {
+                return Arrays.asList("name");
+            }
+        };
+        SolrQueryIndex solrQueryIndex = new SolrQueryIndex("solr", solrServer, configuration);
+
+        FilterImpl filter = new FilterImpl(selector, "select * from [nt:base] as a where name = 'hello')", new QueryEngineSettings());
+        filter.restrictProperty("name", Operator.EQUAL, PropertyValues.newString("hello"));
+        double cost = solrQueryIndex.getCost(filter, root);
+        assertTrue(Double.POSITIVE_INFINITY == cost);
+    }
+
+    @Test
+    public void testQueryOnIgnoredExistingProperty() throws Exception {
+        NodeState root = mock(NodeState.class);
+        when(root.getNames(any(String.class))).thenReturn(Collections.<String>emptySet());
+        SelectorImpl selector = new SelectorImpl(root, "a");
+
+        SolrServer solrServer = TestUtils.createSolrServer();
+        SolrInputDocument document = new SolrInputDocument();
+        document.addField("path_exact", "/a/b");
+        document.addField("name", "hello");
+        solrServer.add(document);
+        solrServer.commit();
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration() {
+            @Override
+            public boolean useForPropertyRestrictions() {
+                return true;
+            }
+
+            @Override
+            public Collection<String> getIgnoredProperties() {
+                return Arrays.asList("name");
+            }
+        };
+        SolrQueryIndex solrQueryIndex = new SolrQueryIndex("solr", solrServer, configuration);
+
+        FilterImpl filter = new FilterImpl(selector, "select * from [nt:base] as a where name = 'hello')", new QueryEngineSettings());
+        filter.restrictProperty("name", Operator.EQUAL, PropertyValues.newString("hello"));
+        String plan = solrQueryIndex.getPlan(filter, root);
+        assertNotNull(plan);
+        assertTrue(plan.contains("q=*%3A*")); // querying on property name is not possible, then falling back to a match all query
+    }
+
+    @Test
+    public void testQueryOnExistingProperty() throws Exception {
+        NodeState root = mock(NodeState.class);
+        when(root.getNames(any(String.class))).thenReturn(Collections.<String>emptySet());
+        SelectorImpl selector = new SelectorImpl(root, "a");
+
+        SolrServer solrServer = TestUtils.createSolrServer();
+        SolrInputDocument document = new SolrInputDocument();
+        document.addField("path_exact", "/a/b");
+        document.addField("name", "hello");
+        solrServer.add(document);
+        solrServer.commit();
+        OakSolrConfiguration configuration = new DefaultSolrConfiguration() {
+            @Override
+            public boolean useForPropertyRestrictions() {
+                return true;
+            }
+        };
+        SolrQueryIndex solrQueryIndex = new SolrQueryIndex("solr", solrServer, configuration);
+
+        FilterImpl filter = new FilterImpl(selector, "select * from [nt:base] as a where name = 'hello')", new QueryEngineSettings());
+        filter.restrictProperty("name", Operator.EQUAL, PropertyValues.newString("hello"));
+        String plan = solrQueryIndex.getPlan(filter, root);
+        assertNotNull(plan);
+        assertTrue(plan.contains("q=name%3Ahello")); // query gets converted to a fielded query on name field
+    }
 }

Modified: jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml?rev=1614689&r1=1614688&r2=1614689&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml Wed Jul 30 15:39:58 2014
@@ -109,11 +109,12 @@
         <field name="path_child" type="children_path" indexed="true" stored="false"/>
         <field name="path_anc" type="parent_path" indexed="true" stored="false"/>
         <field name="path_des" type="descendent_path" indexed="true" stored="false"/>
-        <field name="ignored" type="ignored" multiValued="true"/>
+        <field name="ignored" type="ignored" />
         <field name="catch_all" type="text_general" indexed="true" stored="false" multiValued="true"/>
         <field name="_version_" type="long" indexed="true" stored="true"/>
         <field name=":path" type="string" indexed="true" stored="false"/>
 
+        <field name="jcr:data" type="binary"  indexed="true"  stored="false" multiValued="true"/>
         <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
         <dynamicField name="*_is" type="int"    indexed="true"  stored="true"  multiValued="true"/>
         <dynamicField name="*_s"  type="string"  indexed="true"  stored="true" />
@@ -143,6 +144,7 @@
 
         <dynamicField name="*_pi"  type="pint"    indexed="true"  stored="true"/>
         <dynamicField name="*_c"   type="currency" indexed="true"  stored="true"/>
+        <dynamicField name="*_bin" type="binary"  indexed="true"  stored="false" multiValued="true"/>
         <dynamicField name="*" type="text_general" indexed="true" stored="true" multiValued="true"/>
     </fields>
     <uniqueKey>path_exact</uniqueKey>