You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2010/09/29 14:58:27 UTC

svn commit: r1002596 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java test/java/org/apache/jackrabbit/core/query/FulltextQueryTest.java

Author: mreutegg
Date: Wed Sep 29 12:58:27 2010
New Revision: 1002596

URL: http://svn.apache.org/viewvc?rev=1002596&view=rev
Log:
JCR-2759: Collapse nested OR expressions

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/FulltextQueryTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java?rev=1002596&r1=1002595&r2=1002596&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java Wed Sep 29 12:58:27 2010
@@ -69,6 +69,7 @@ import org.apache.lucene.analysis.Analyz
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queryParser.ParseException;
 import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.BooleanClause.Occur;
@@ -265,7 +266,28 @@ public class LuceneQueryBuilder implemen
         Object[] result = node.acceptOperands(this, null);
         for (Object aResult : result) {
             Query operand = (Query) aResult;
-            orQuery.add(operand, Occur.SHOULD);
+            if (operand instanceof BooleanQuery) {
+                // check if the clauses are all optional, then
+                // we can collapse into the the enclosing orQuery
+                boolean hasNonOptional = false;
+                for (BooleanClause clause : ((BooleanQuery) operand).getClauses()) {
+                    if (clause.isProhibited() || clause.isRequired()) {
+                        hasNonOptional = true;
+                        break;
+                    }
+                }
+                if (hasNonOptional) {
+                    // cannot collapse
+                    orQuery.add(operand, Occur.SHOULD);
+                } else {
+                    // collapse
+                    for (BooleanClause clause : ((BooleanQuery) operand).getClauses()) {
+                        orQuery.add(clause);
+                    }
+                }
+            } else {
+                orQuery.add(operand, Occur.SHOULD);
+            }
         }
         return orQuery;
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/FulltextQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/FulltextQueryTest.java?rev=1002596&r1=1002595&r2=1002596&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/FulltextQueryTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/FulltextQueryTest.java Wed Sep 29 12:58:27 2010
@@ -17,6 +17,9 @@
 package org.apache.jackrabbit.core.query;
 
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
@@ -24,6 +27,9 @@ import javax.jcr.nodetype.NodeType;
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryResult;
+import javax.jcr.query.Row;
+
+import org.apache.jackrabbit.commons.iterator.RowIterable;
 
 /**
  * Performs tests with the <code>CONTAINS</code> function.
@@ -267,6 +273,46 @@ public class FulltextQueryTest extends A
         executeContainsQuery("foo:bar", "foo:bar", true);
     }
 
+    public void testMultipleOrExpressions() throws RepositoryException {
+        Node n = testRootNode.addNode("node1");
+        n.setProperty("prop1", "foo");
+        n.setProperty("prop2", "bar");
+        n.setProperty("prop3", "baz");
+
+        n = testRootNode.addNode("node2");
+        n.setProperty("prop1", "bar");
+        n.setProperty("prop2", "foo");
+        n.setProperty("prop3", "baz");
+
+        n = testRootNode.addNode("node3");
+        n.setProperty("prop1", "bar");
+        n.setProperty("prop2", "baz");
+        n.setProperty("prop3", "foo");
+
+        superuser.save();
+
+        List<String> r1 = new ArrayList<String>();
+        QueryResult result = qm.createQuery(testPath + "/*[jcr:contains(@prop1, 'foo') or jcr:contains(@prop2, 'foo') or jcr:contains(@prop3, 'foo')] order by @jcr:score descending", Query.XPATH).execute();
+        for (Row r : new RowIterable(result.getRows())) {
+            r1.add(r.getPath() + ":" + (int) (r.getScore() * 1000));
+        }
+
+        List<String> r2 = new ArrayList<String>();
+        result = qm.createQuery(testPath + "/*[jcr:contains(@prop3, 'foo') or jcr:contains(@prop1, 'foo') or jcr:contains(@prop2, 'foo')] order by @jcr:score descending", Query.XPATH).execute();
+        for (Row r : new RowIterable(result.getRows())) {
+            r2.add(r.getPath() + ":" + (int) (r.getScore() * 1000));
+        }
+
+        List<String> r3 = new ArrayList<String>();
+        result = qm.createQuery(testPath + "/*[jcr:contains(@prop2, 'foo') or jcr:contains(@prop3, 'foo') or jcr:contains(@prop1, 'foo')] order by @jcr:score descending", Query.XPATH).execute();
+        for (Row r : new RowIterable(result.getRows())) {
+            r3.add(r.getPath() + ":" + (int) (r.getScore() * 1000));
+        }
+
+        assertEquals(r1, r2);
+        assertEquals(r1, r3);
+    }
+
     /**
      * Executes a query and checks if the query matched the test node.
      *