Author: tommaso
Date: Mon Jul 27 21:16:08 2015
New Revision: 1692955
URL: http://svn.apache.org/r1692955
Log:
OAK-3147 - configurable jcr:content descendants collapsing
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/OakSolrConfigurationDefaults.java
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/nodestate/OakSolrNodeStateConfiguration.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/FilterQueryParser.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/FilterQueryParserTest.java
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.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=1692955&r1=1692954&r2=1692955&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
Mon Jul 27 21:16:08 2015
@@ -121,4 +121,15 @@ public class DefaultSolrConfiguration im
return usedProperties;
}
+ @Override
+ public boolean collapseJcrContentNodes() {
+ return OakSolrConfigurationDefaults.COLLAPSE_JCR_CONTENT_NODES;
+ }
+
+ @Nonnull
+ @Override
+ public String getCollapsedPathField() {
+ return OakSolrConfigurationDefaults.COLLAPSED_PATH_FIELD;
+ }
+
}
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=1692955&r1=1692954&r2=1692955&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
Mon Jul 27 21:16:08 2015
@@ -132,6 +132,25 @@ public interface OakSolrConfiguration {
Collection<String> getUsedProperties();
/**
+ * Make all nodes / documents matching a query that are descendants of a
'jcr:content' node collapse into such a
+ * node. That will result in resultsets being tipically much more compact
in cases where most / all of the matching
+ * nodes match such a hierarchy.
+ *
+ * @return {@code true} if only the 'jcr:content' node should be returned
for all its the matching descendants,
+ * {@code false} otherwise
+ */
+ boolean collapseJcrContentNodes();
+
+ /**
+ * Provide the name of the field to be used for indexing the collapsed
path of each node when {@link #collapseJcrContentNodes()}
+ * is set to {@code true}.
+ *
+ * @return the name of the Solr field to be used for indexing and
searching on collapsed paths.
+ */
+ @Nonnull
+ String getCollapsedPathField();
+
+ /**
* Enum for describing Solr commit policy used in a certain instance
*/
enum CommitPolicy {
Modified:
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfigurationDefaults.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfigurationDefaults.java?rev=1692955&r1=1692954&r2=1692955&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfigurationDefaults.java
(original)
+++
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/OakSolrConfigurationDefaults.java
Mon Jul 27 21:16:08 2015
@@ -38,5 +38,6 @@ public class OakSolrConfigurationDefault
Arrays.asList("rep:members", "rep:authorizableId", "jcr:uuid",
"rep:principalName", "rep:password"));
public static final String TYPE_MAPPINGS = "";
public static final String PROPERTY_MAPPINGS = "";
-
+ public static final boolean COLLAPSE_JCR_CONTENT_NODES = false;
+ public static final String COLLAPSED_PATH_FIELD = "path_collapsed";
}
Modified:
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/nodestate/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/nodestate/OakSolrNodeStateConfiguration.java?rev=1692955&r1=1692954&r2=1692955&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/nodestate/OakSolrNodeStateConfiguration.java
(original)
+++
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/nodestate/OakSolrNodeStateConfiguration.java
Mon Jul 27 21:16:08 2015
@@ -179,6 +179,17 @@ public class OakSolrNodeStateConfigurati
return usedProperties;
}
+ @Override
+ public boolean collapseJcrContentNodes() {
+ return getBooleanValueFor(Properties.COLLAPSE_JCR_CONTENT_NODES,
OakSolrConfigurationDefaults.COLLAPSE_JCR_CONTENT_NODES);
+ }
+
+ @Nonnull
+ @Override
+ public String getCollapsedPathField() {
+ return getStringValueFor(Properties.COLLAPSED_PATH_FIELD,
OakSolrConfigurationDefaults.COLLAPSED_PATH_FIELD);
+ }
+
private boolean getBooleanValueFor(String propertyName, boolean
defaultValue) {
boolean value = defaultValue;
PropertyState property = definition.getProperty(propertyName);
@@ -228,6 +239,7 @@ public class OakSolrNodeStateConfigurati
public final class Properties {
// --> oak solr config properties <--
public static final String PATH_FIELD = "pathField";
+ public static final String COLLAPSED_PATH_FIELD = "pathField";
public static final String PARENT_FIELD = "parentField";
public static final String CHILDREN_FIELD = "childrenField";
public static final String DESCENDANTS_FIELD = "descendantsField";
@@ -241,6 +253,6 @@ public class OakSolrNodeStateConfigurati
public static final String TYPE_MAPPINGS = "typeMappings";
public static final String PROPERTY_MAPPINGS = "propertyMappings";
public static final String USED_PROPERTIES = "usedProperties";
-
+ public static final String COLLAPSE_JCR_CONTENT_NODES =
"collapseJcrContentNodes";
}
}
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=1692955&r1=1692954&r2=1692955&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
Mon Jul 27 21:16:08 2015
@@ -210,6 +210,18 @@ class SolrIndexEditor implements IndexEd
SolrInputDocument inputDocument = new SolrInputDocument();
String path = getPath();
inputDocument.addField(configuration.getPathField(), path);
+
+ if (configuration.collapseJcrContentNodes()) {
+ int jcrContentIndex = path.lastIndexOf(JcrConstants.JCR_CONTENT);
+ if (jcrContentIndex >= 0) {
+ int index = jcrContentIndex +
JcrConstants.JCR_CONTENT.length();
+ String collapsedPath = path.substring(0, index);
+ inputDocument.addField(configuration.getCollapsedPathField(),
collapsedPath);
+ } else {
+ inputDocument.addField(configuration.getCollapsedPathField(),
path);
+ }
+ }
+
for (PropertyState property : state.getProperties()) {
if ((configuration.getUsedProperties().size() > 0 &&
configuration.getUsedProperties().contains(property.getName()))
||
!configuration.getIgnoredProperties().contains(property.getName())) {
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=1692955&r1=1692954&r2=1692955&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
Mon Jul 27 21:16:08 2015
@@ -59,6 +59,9 @@ public class OakSolrConfigurationProvide
@Property(value = OakSolrConfigurationDefaults.CATCHALL_FIELD, label =
"catch all field")
private static final String CATCH_ALL_FIELD = "catch.all.field";
+ @Property(value = OakSolrConfigurationDefaults.COLLAPSED_PATH_FIELD, label
= "field for collapsing jcr:content paths")
+ private static final String COLLAPSED_PATH_FIELD = "collapsed.path.field";
+
@Property(options = {
@PropertyOption(name = "HARD",
value = "Hard commit"
@@ -73,7 +76,6 @@ public class OakSolrConfigurationProvide
)
private static final String COMMIT_POLICY = "commit.policy";
-
@Property(intValue = OakSolrConfigurationDefaults.ROWS, label = "rows")
private static final String ROWS = "rows";
@@ -103,10 +105,14 @@ public class OakSolrConfigurationProvide
"mappings from JCR property names to Solr fields")
private static final String PROPERTY_MAPPINGS = "property.mappings";
+ @Property(boolValue =
OakSolrConfigurationDefaults.COLLAPSE_JCR_CONTENT_NODES, label = "collapse
jcr:content nodes")
+ private static final String COLLAPSE_JCR_CONTENT_NODES =
"collapse.jcrcontent.nodes";
+
private String pathChildrenFieldName;
private String pathParentFieldName;
private String pathDescendantsFieldName;
private String pathExactFieldName;
+ private String collapsedPathField;
private String catchAllField;
private OakSolrConfiguration.CommitPolicy commitPolicy;
private int rows;
@@ -117,6 +123,7 @@ public class OakSolrConfigurationProvide
private String[] usedProperties;
private String[] typeMappings;
private String[] propertyMappings;
+ private boolean collapseJcrContentNodes;
private OakSolrConfiguration oakSolrConfiguration;
@@ -125,6 +132,7 @@ public class OakSolrConfigurationProvide
pathChildrenFieldName =
String.valueOf(componentContext.getProperties().get(PATH_CHILDREN_FIELD));
pathParentFieldName =
String.valueOf(componentContext.getProperties().get(PATH_PARENT_FIELD));
pathExactFieldName =
String.valueOf(componentContext.getProperties().get(PATH_EXACT_FIELD));
+ collapsedPathField=
String.valueOf(componentContext.getProperties().get(COLLAPSED_PATH_FIELD));
pathDescendantsFieldName =
String.valueOf(componentContext.getProperties().get(PATH_DESCENDANTS_FIELD));
catchAllField =
String.valueOf(componentContext.getProperties().get(CATCH_ALL_FIELD));
rows =
Integer.parseInt(String.valueOf(componentContext.getProperties().get(ROWS)));
@@ -136,6 +144,7 @@ public class OakSolrConfigurationProvide
ignoredProperties =
PropertiesUtil.toStringArray(componentContext.getProperties().get(IGNORED_PROPERTIES));
usedProperties =
PropertiesUtil.toStringArray(componentContext.getProperties().get(USED_PROPERTIES));
propertyMappings =
PropertiesUtil.toStringArray(componentContext.getProperties().get(PROPERTY_MAPPINGS));
+ collapseJcrContentNodes =
Boolean.valueOf(String.valueOf(componentContext.getProperties().get(COLLAPSE_JCR_CONTENT_NODES)));
}
@Deactivate
@@ -262,6 +271,17 @@ public class OakSolrConfigurationProvide
return Collections.emptyList();
}
}
+
+ @Override
+ public boolean collapseJcrContentNodes() {
+ return collapseJcrContentNodes;
+ }
+
+ @Nonnull
+ @Override
+ public String getCollapsedPathField() {
+ return collapsedPathField;
+ }
};
}
return oakSolrConfiguration;
Modified:
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java?rev=1692955&r1=1692954&r2=1692955&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java
(original)
+++
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java
Mon Jul 27 21:16:08 2015
@@ -234,6 +234,10 @@ class FilterQueryParser {
}
}
+ if (configuration.collapseJcrContentNodes()) {
+ solrQuery.addFilterQuery("{!collapse field=" +
configuration.getCollapsedPathField() + "}");
+ }
+
if (queryBuilder.length() == 0) {
queryBuilder.append("*:*");
}
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=1692955&r1=1692954&r2=1692955&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
Mon Jul 27 21:16:08 2015
@@ -118,6 +118,7 @@
<field name=":indexed" type="tdate" indexed="true" stored="false"
default="NOW" docValues="true"/>
<field name=":suggest-weight" type="tint" indexed="false"
stored="false" default="1" docValues="true"/>
<field name=":suggest" type="string" indexed="true" stored="true"
multiValued="true" />
+ <field name="path_collapsed" type="string" indexed="true"
stored="false"/>
<field name="_version_" type="long" indexed="true" stored="true"/>
<!-- sorting dynamic fields -->
Modified:
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParserTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParserTest.java?rev=1692955&r1=1692954&r2=1692955&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParserTest.java
(original)
+++
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParserTest.java
Mon Jul 27 21:16:08 2015
@@ -22,8 +22,11 @@ import org.apache.jackrabbit.oak.spi.que
import org.apache.solr.client.solrj.SolrQuery;
import org.junit.Test;
+import java.util.Arrays;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -57,7 +60,8 @@ public class FilterQueryParserTest {
when(filter.getPath()).thenReturn("/");
SolrQuery solrQuery = FilterQueryParser.getQuery(filter, null,
configuration);
assertNotNull(solrQuery);
-
assertEquals(configuration.getFieldForPathRestriction(pathRestriction)+":\\/",
solrQuery.get("fq"));
+ String[] filterQueries = solrQuery.getFilterQueries();
+
assertTrue(Arrays.asList(filterQueries).contains(configuration.getFieldForPathRestriction(pathRestriction)
+ ":\\/"));
assertEquals("*:*", solrQuery.get("q"));
}
Modified:
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java?rev=1692955&r1=1692954&r2=1692955&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java
(original)
+++
jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java
Mon Jul 27 21:16:08 2015
@@ -296,20 +296,27 @@ public class SolrIndexQueryTestIT extend
public void testRepSimilarXPathQuery() throws Exception {
String query = "//element(*, nt:base)[rep:similar(., '/test/a')]";
Tree test = root.getTree("/").addChild("test");
- test.addChild("a").setProperty("text", "Hello World Hello World");
- test.addChild("b").setProperty("text", "Hello World");
- test.addChild("c").setProperty("text", "World");
- test.addChild("d").setProperty("text", "Hello");
- test.addChild("e").setProperty("text", "World");
- test.addChild("f").setProperty("text", "Hello");
- test.addChild("g").setProperty("text", "World");
- test.addChild("h").setProperty("text", "Hello");
+ test.addChild("a").setProperty("text", "the quick brown fox jumped
over the lazy white dog");
+ test.addChild("b").setProperty("text", "I am a dog");
+ test.addChild("c").setProperty("text", "dogs don't hurt");
+ test.addChild("d").setProperty("text", "white men can't jump");
+ test.addChild("e").setProperty("text", "the fox is brown");
+ test.addChild("f").setProperty("text", "a quickest dog jumped over the
quick white dog");
+ test.addChild("g").setProperty("text", "hello world");
+ test.addChild("h").setProperty("text", "over the lazy top");
root.commit();
Iterator<String> result = executeQuery(query, "xpath").iterator();
assertTrue(result.hasNext());
assertEquals("/test/b", result.next());
assertTrue(result.hasNext());
- assertEquals("/test/c", result.next());
+ assertEquals("/test/d", result.next());
+ assertTrue(result.hasNext());
+ assertEquals("/test/e", result.next());
+ assertTrue(result.hasNext());
+ assertEquals("/test/f", result.next());
+ assertTrue(result.hasNext());
+ assertEquals("/test/h", result.next());
+ assertFalse(result.hasNext());
}
@Test
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=1692955&r1=1692954&r2=1692955&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
Mon Jul 27 21:16:08 2015
@@ -126,11 +126,12 @@
<field name="path_des" type="descendent_path" indexed="true"
stored="false"/>
<field name="ignored" type="ignored" />
<field name="catch_all" type="text_general" indexed="true"
stored="false" multiValued="true" termVectors="true"/> <!-- term vectors used
for rep:similar -->
- <field name="_version_" type="long" indexed="true" stored="true"/>
<field name=":path" type="string" indexed="true" stored="false"/>
<field name=":indexed" type="tdate" indexed="true" stored="false"
default="NOW" docValues="true"/>
<field name=":suggest-weight" type="tint" indexed="false"
stored="false" default="1" docValues="true"/>
<field name=":suggest" type="string" indexed="true" stored="true"
multiValued="true" />
+ <field name="path_collapsed" type="string" indexed="true"
stored="true"/>
+ <field name="_version_" type="long" indexed="true" stored="true"/>
<!-- sorting dynamic fields -->
<dynamicField name="*_double_sort" type="tdouble" indexed="false"
stored="false" multiValued="false" docValues="true"/>