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>