You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by am...@apache.org on 2014/12/15 08:27:11 UTC
svn commit: r1645585 - in /jackrabbit/oak/trunk/oak-lucene/src:
main/java/org/apache/jackrabbit/oak/plugins/index/lucene/
test/java/org/apache/jackrabbit/oak/plugins/index/lucene/
Author: amitj
Date: Mon Dec 15 07:27:10 2014
New Revision: 1645585
URL: http://svn.apache.org/r1645585
Log:
OAK-2353: Support for "order by jcr:score descending" in lucene property index
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java?rev=1645585&r1=1645584&r2=1645585&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java Mon Dec 15 07:27:10 2014
@@ -49,6 +49,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.plugins.tree.ImmutableTree;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -64,6 +65,7 @@ import static com.google.common.collect.
import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.jackrabbit.JcrConstants.JCR_SCORE;
import static org.apache.jackrabbit.JcrConstants.NT_BASE;
import static org.apache.jackrabbit.oak.api.Type.NAMES;
import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;
@@ -115,6 +117,12 @@ class IndexDefinition implements Aggrega
static final int TYPES_ALLOW_ALL = -1;
+ /**
+ * native sort order
+ */
+ static final OrderEntry NATIVE_SORT_ORDER = new OrderEntry(JCR_SCORE, Type.UNDEFINED,
+ OrderEntry.Order.DESCENDING);
+
private final boolean fullTextEnabled;
private final NodeState definition;
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java?rev=1645585&r1=1645584&r2=1645585&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java Mon Dec 15 07:27:10 2014
@@ -323,8 +323,12 @@ class IndexPlanner {
&& !o.getPropertyType().isArray()) {
orderEntries.add(o); //Lucene can manage any order desc/asc
result.sortedProperties.add(pd);
+ } else if (o.getPropertyName().equals(IndexDefinition.NATIVE_SORT_ORDER.getPropertyName())) {
+ // Supports jcr:score descending natively
+ orderEntries.add(IndexDefinition.NATIVE_SORT_ORDER);
}
}
+
//TODO Should we return order entries only when all order clauses are satisfied
return orderEntries;
}
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java?rev=1645585&r1=1645584&r2=1645585&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java Mon Dec 15 07:27:10 2014
@@ -95,6 +95,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.oak.api.Type.LONG;
@@ -103,6 +104,7 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;
import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldNames.PATH;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.NATIVE_SORT_ORDER;
import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.VERSION;
import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newAncestorTerm;
import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newFulltextTerm;
@@ -368,17 +370,35 @@ public class LucenePropertyIndex impleme
if (sortOrder == null || sortOrder.isEmpty()) {
return null;
}
- SortField[] fields = new SortField[sortOrder.size()];
+
+ List<SortField> fieldsList = newArrayListWithCapacity(sortOrder.size());
PlanResult planResult = pr(plan);
for (int i = 0; i < sortOrder.size(); i++) {
- PropertyDefinition pd = planResult.getOrderedProperty(i);
OrderEntry oe = sortOrder.get(i);
- boolean reverse = oe.getOrder() != OrderEntry.Order.ASCENDING;
- String propName = oe.getPropertyName();
- propName = FieldNames.createDocValFieldName(propName);
- fields[i] = new SortField(propName, toLuceneSortType(oe, pd), reverse);
+ if (!isNativeSort(oe)) {
+ PropertyDefinition pd = planResult.getOrderedProperty(i);
+ boolean reverse = oe.getOrder() != OrderEntry.Order.ASCENDING;
+ String propName = oe.getPropertyName();
+ propName = FieldNames.createDocValFieldName(propName);
+ fieldsList.add(new SortField(propName, toLuceneSortType(oe, pd), reverse));
+ }
+ }
+
+ if (fieldsList.isEmpty()) {
+ return null;
+ } else {
+ return new Sort(fieldsList.toArray(new SortField[0]));
}
- return new Sort(fields);
+ }
+
+ /**
+ * Identifies the default sort order used by the index (@jcr:score descending)
+ *
+ * @param oe order entry
+ * @return
+ */
+ private static boolean isNativeSort(OrderEntry oe) {
+ return oe.getPropertyName().equals(NATIVE_SORT_ORDER.getPropertyName());
}
private static SortField.Type toLuceneSortType(OrderEntry oe, PropertyDefinition defn) {
@@ -468,12 +488,14 @@ public class LucenePropertyIndex impleme
List<OrderEntry> orders = plan.getSortOrder();
for (int i = 0; i < orders.size(); i++) {
OrderEntry oe = orders.get(i);
- PropertyDefinition pd = planResult.getOrderedProperty(i);
- PropertyRestriction orderRest = new PropertyRestriction();
- orderRest.propertyName = oe.getPropertyName();
- Query q = createQuery(orderRest, pd);
- if (q != null) {
- qs.add(q);
+ if (!isNativeSort(oe)) {
+ PropertyDefinition pd = planResult.getOrderedProperty(i);
+ PropertyRestriction orderRest = new PropertyRestriction();
+ orderRest.propertyName = oe.getPropertyName();
+ Query q = createQuery(orderRest, pd);
+ if (q != null) {
+ qs.add(q);
+ }
}
}
}
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1645585&r1=1645584&r2=1645585&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java Mon Dec 15 07:27:10 2014
@@ -32,10 +32,13 @@ import com.google.common.collect.Compari
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.Oak;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.ResultRow;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
@@ -52,6 +55,7 @@ import org.junit.Test;
import static com.google.common.collect.ImmutableSet.of;
import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.oak.api.QueryEngine.NO_MAPPINGS;
import static org.apache.jackrabbit.oak.api.Type.STRINGS;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE;
@@ -773,6 +777,65 @@ public class LucenePropertyIndexTest ext
}
@Test
+ public void sortQueriesWithJcrScore() throws Exception {
+ Tree idx = createIndex("test1", of("propa", "n0", "n1", "n2"));
+ root.commit();
+
+ Tree test = root.getTree("/").addChild("test");
+ for(int i = 3; i > 0; i--){
+ Tree child = test.addChild("n" + i);
+ child.setProperty("propa", "foo");
+ }
+ root.commit();
+
+ // Descending matches with lucene native sort
+ String query =
+ "measure select [jcr:path] from [nt:base] where [propa] = 'foo' order by [jcr:score] desc";
+ assertThat(measureWithLimit(query, SQL2, 1), containsString("scanCount: 1"));
+
+ // Ascending needs to be sorted by query engine
+ query =
+ "measure select [jcr:path] from [nt:base] where [propa] = 'foo' order by [jcr:score]";
+ assertThat(measureWithLimit(query, SQL2, 1), containsString("scanCount: 3"));
+ }
+
+ @Test
+ public void sortFulltextQueriesWithJcrScore() throws Exception {
+ // Index Definition
+ Tree idx = createIndex("test1", of("propa"));
+ idx.setProperty(LuceneIndexConstants.FULL_TEXT_ENABLED, true);
+ useV2(idx);
+
+ // create test data
+ Tree test = root.getTree("/").addChild("test");
+ root.commit();
+ test.addChild("a").setProperty("propa", "foo");
+ test.addChild("b").setProperty("propa", "foo");
+ test.addChild("c").setProperty("propa", "foo");
+ root.commit();
+
+ // Descending matches with lucene native sort
+ String query = "measure //*[jcr:contains(., 'foo' )] order by @jcr:score descending";
+ assertThat(measureWithLimit(query, XPATH, 1), containsString("scanCount: 1"));
+
+ // Ascending needs to be sorted by query engine
+ query = "measure //*[jcr:contains(., 'foo' )] order by @jcr:score";
+ assertThat(measureWithLimit(query, XPATH, 1), containsString("scanCount: 3"));
+ }
+
+ private String measureWithLimit(String query, String lang, int limit) throws ParseException {
+ List<? extends ResultRow> result = Lists.newArrayList(
+ qe.executeQuery(query, lang, limit, 0, Maps.<String, PropertyValue>newHashMap(),
+ NO_MAPPINGS).getRows());
+
+ String measure = "";
+ if (result.size() > 0) {
+ measure = result.get(0).toString();
+ }
+ return measure;
+ }
+
+ @Test
public void indexTimeFieldBoostAndRelativeProperty() throws Exception {
// Index Definition
Tree index = root.getTree("/");