You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2013/01/25 14:11:08 UTC

svn commit: r1438485 - in /lucene/dev/trunk/lucene: ./ facet/src/examples/org/apache/lucene/facet/example/simple/ facet/src/java/org/apache/lucene/facet/search/ facet/src/test/org/apache/lucene/facet/index/ facet/src/test/org/apache/lucene/facet/search/

Author: shaie
Date: Fri Jan 25 13:11:08 2013
New Revision: 1438485

URL: http://svn.apache.org/viewvc?rev=1438485&view=rev
Log:
LUCENE-4716: Add OR support to DrillDown

Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java
    lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java
    lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java
    lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1438485&r1=1438484&r2=1438485&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Fri Jan 25 13:11:08 2013
@@ -76,6 +76,9 @@ New Features
 API Changes
 
 * LUCENE-4709: FacetResultNode no longer has a residue field. (Shai Erera)
+
+* LUCENE-4716: DrillDown.query now takes Occur, allowing to specify if
+  categories should be OR'ed or AND'ed. (Shai Erera)
   
 Bug Fixes
 

Modified: lucene/dev/trunk/lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java?rev=1438485&r1=1438484&r2=1438485&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java (original)
+++ lucene/dev/trunk/lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java Fri Jan 25 13:11:08 2013
@@ -1,6 +1,5 @@
 package org.apache.lucene.facet.example.simple;
 
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
@@ -17,6 +16,7 @@ import org.apache.lucene.facet.taxonomy.
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MultiCollector;
 import org.apache.lucene.search.Query;
@@ -153,7 +153,7 @@ public class SimpleSearcher {
     CategoryPath categoryOfInterest = resIterator.next().label;
     
     // drill-down preparation: turn the base query into a drill-down query for the category of interest
-    Query q2 = DrillDown.query(indexingParams, baseQuery, categoryOfInterest);
+    Query q2 = DrillDown.query(indexingParams, baseQuery, Occur.MUST, categoryOfInterest);
     
     // that's it - search with the new query and we're done!
     // only documents both matching the base query AND containing the 

Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java?rev=1438485&r1=1438484&r2=1438485&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java Fri Jan 25 13:11:08 2013
@@ -59,18 +59,23 @@ public final class DrillDown {
   }
   
   /**
-   * Wraps a given {@link Query} as a drill-down query over the given
-   * categories, assuming all are required (e.g. {@code AND}). You can construct
-   * a query with different modes (such as {@code OR} or {@code AND} of
-   * {@code ORs}) by creating a {@link BooleanQuery} and call this method
-   * several times. Make sure to wrap the query in that case by
-   * {@link ConstantScoreQuery} and set the boost to 0.0f, so that it doesn't
-   * affect scoring.
+   * Wraps a given {@link Query} by a drill-down query over the given
+   * categories. {@link Occur} defines the relationship between the cateories
+   * (e.g. {@code OR} or {@code AND}. If you need to construct a more
+   * complicated relationship, e.g. {@code AND} of {@code ORs}), call this
+   * method with every group of categories with the same relationship and then
+   * construct a {@link BooleanQuery} which will wrap all returned queries. It
+   * is advised to construct that boolean query with coord disabled, and also
+   * wrap the final query with {@link ConstantScoreQuery} and set its boost to
+   * {@code 0.0f}.
+   * <p>
+   * <b>NOTE:</b> {@link Occur} only makes sense when there is more than one
+   * {@link CategoryPath} given.
    * <p>
    * <b>NOTE:</b> {@code baseQuery} can be {@code null}, in which case only the
    * {@link Query} over the categories will is returned.
    */
-  public static final Query query(FacetIndexingParams iParams, Query baseQuery, CategoryPath... paths) {
+  public static final Query query(FacetIndexingParams iParams, Query baseQuery, Occur occur, CategoryPath... paths) {
     if (paths == null || paths.length == 0) {
       throw new IllegalArgumentException("Empty category path not allowed for drill down query!");
     }
@@ -81,7 +86,7 @@ public final class DrillDown {
     } else {
       BooleanQuery bq = new BooleanQuery(true); // disable coord
       for (CategoryPath cp : paths) {
-        bq.add(new TermQuery(term(iParams, cp)), Occur.MUST);
+        bq.add(new TermQuery(term(iParams, cp)), occur);
       }
       q = bq;
     }
@@ -100,10 +105,10 @@ public final class DrillDown {
   }
 
   /**
-   * @see #query(FacetIndexingParams, Query, CategoryPath...)
+   * @see #query
    */
-  public static final Query query(FacetSearchParams sParams, Query baseQuery, CategoryPath... paths) {
-    return query(sParams.indexingParams, baseQuery, paths);
+  public static final Query query(FacetSearchParams sParams, Query baseQuery, Occur occur, CategoryPath... paths) {
+    return query(sParams.indexingParams, baseQuery, occur, paths);
   }
 
 }

Modified: lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java?rev=1438485&r1=1438484&r2=1438485&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java (original)
+++ lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java Fri Jan 25 13:11:08 2013
@@ -58,6 +58,7 @@ import org.apache.lucene.search.MultiCol
 import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TotalHitCountCollector;
+import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.IOUtils;
@@ -284,7 +285,7 @@ public class TestFacetsPayloadMigrationR
     for (String dim : expectedCounts.keySet()) {
       CategoryPath drillDownCP = new CategoryPath(dim);
       FacetSearchParams fsp = new FacetSearchParams(fip, new CountFacetRequest(drillDownCP, 10));
-      Query drillDown = DrillDown.query(fsp, new MatchAllDocsQuery(), drillDownCP);
+      Query drillDown = DrillDown.query(fsp, new MatchAllDocsQuery(), Occur.MUST, drillDownCP);
       TotalHitCountCollector total = new TotalHitCountCollector();
       FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader);
       searcher.search(drillDown, MultiCollector.wrap(fc, total));

Modified: lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java?rev=1438485&r1=1438484&r2=1438485&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java Fri Jan 25 13:11:08 2013
@@ -27,6 +27,7 @@ import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.store.Directory;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -129,25 +130,25 @@ public class DrillDownTest extends Facet
     IndexSearcher searcher = newSearcher(reader);
 
     // Making sure the query yields 25 documents with the facet "a"
-    Query q = DrillDown.query(defaultParams, null, new CategoryPath("a"));
+    Query q = DrillDown.query(defaultParams, null, Occur.MUST, new CategoryPath("a"));
     TopDocs docs = searcher.search(q, 100);
     assertEquals(25, docs.totalHits);
     
     // Making sure the query yields 5 documents with the facet "b" and the
     // previous (facet "a") query as a base query
-    Query q2 = DrillDown.query(defaultParams, q, new CategoryPath("b"));
+    Query q2 = DrillDown.query(defaultParams, q, Occur.MUST, new CategoryPath("b"));
     docs = searcher.search(q2, 100);
     assertEquals(5, docs.totalHits);
 
     // Making sure that a query of both facet "a" and facet "b" yields 5 results
-    Query q3 = DrillDown.query(defaultParams, null, new CategoryPath("a"), new CategoryPath("b"));
+    Query q3 = DrillDown.query(defaultParams, null, Occur.MUST, new CategoryPath("a"), new CategoryPath("b"));
     docs = searcher.search(q3, 100);
     assertEquals(5, docs.totalHits);
     
     // Check that content:foo (which yields 50% results) and facet/b (which yields 20%)
     // would gather together 10 results (10%..) 
     Query fooQuery = new TermQuery(new Term("content", "foo"));
-    Query q4 = DrillDown.query(defaultParams, fooQuery, new CategoryPath("b"));
+    Query q4 = DrillDown.query(defaultParams, fooQuery, Occur.MUST, new CategoryPath("b"));
     docs = searcher.search(q4, 100);
     assertEquals(10, docs.totalHits);
   }
@@ -157,18 +158,18 @@ public class DrillDownTest extends Facet
     IndexSearcher searcher = newSearcher(reader);
 
     // Create the base query to start with
-    Query q = DrillDown.query(defaultParams, null, new CategoryPath("a"));
+    Query q = DrillDown.query(defaultParams, null, Occur.MUST, new CategoryPath("a"));
     
     // Making sure the query yields 5 documents with the facet "b" and the
     // previous (facet "a") query as a base query
-    Query q2 = DrillDown.query(defaultParams, q, new CategoryPath("b"));
+    Query q2 = DrillDown.query(defaultParams, q, Occur.MUST, new CategoryPath("b"));
     TopDocs docs = searcher.search(q2, 100);
     assertEquals(5, docs.totalHits);
 
     // Check that content:foo (which yields 50% results) and facet/b (which yields 20%)
     // would gather together 10 results (10%..) 
     Query fooQuery = new TermQuery(new Term("content", "foo"));
-    Query q4 = DrillDown.query(defaultParams, fooQuery, new CategoryPath("b"));
+    Query q4 = DrillDown.query(defaultParams, fooQuery, Occur.MUST, new CategoryPath("b"));
     docs = searcher.search(q4, 100);
     assertEquals(10, docs.totalHits);
   }
@@ -203,7 +204,7 @@ public class DrillDownTest extends Facet
     }
     
     // create a drill-down query with category "a", scores should not change
-    q = DrillDown.query(defaultParams, q, new CategoryPath("a"));
+    q = DrillDown.query(defaultParams, q, Occur.MUST, new CategoryPath("a"));
     docs = searcher.search(q, reader.maxDoc()); // fetch all available docs to this query
     for (ScoreDoc sd : docs.scoreDocs) {
       assertEquals("score of doc=" + sd.doc + " modified", scores[sd.doc], sd.score, 0f);
@@ -215,11 +216,21 @@ public class DrillDownTest extends Facet
     // verify that drill-down queries (with no base query) returns 0.0 score
     IndexSearcher searcher = newSearcher(reader);
     
-    Query q = DrillDown.query(defaultParams, null, new CategoryPath("a"));
+    Query q = DrillDown.query(defaultParams, null, Occur.MUST, new CategoryPath("a"));
     TopDocs docs = searcher.search(q, reader.maxDoc()); // fetch all available docs to this query
     for (ScoreDoc sd : docs.scoreDocs) {
       assertEquals(0f, sd.score, 0f);
     }
   }
+  
+  @Test
+  public void testOrQuery() throws Exception {
+    IndexSearcher searcher = newSearcher(reader);
+
+    // Making sure that a query of facet "a" or facet "b" yields 0 results
+    Query q = DrillDown.query(defaultParams, null, Occur.SHOULD, new CategoryPath("a"), new CategoryPath("b"));
+    TopDocs docs = searcher.search(q, 100);
+    assertEquals(40, docs.totalHits);
+  }
     
 }

Modified: lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java?rev=1438485&r1=1438484&r2=1438485&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java (original)
+++ lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java Fri Jan 25 13:11:08 2013
@@ -40,6 +40,7 @@ import org.apache.lucene.index.RandomInd
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.Query;
+import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.store.Directory;
 
 public class TestDemoFacets extends FacetTestCase {
@@ -111,7 +112,7 @@ public class TestDemoFacets extends Face
     
     // Now user drills down on Publish Date/2010:
     fsp = new FacetSearchParams(new CountFacetRequest(new CategoryPath("Author"), 10));
-    Query q2 = DrillDown.query(fsp, new MatchAllDocsQuery(), new CategoryPath("Publish Date/2010", '/'));
+    Query q2 = DrillDown.query(fsp, new MatchAllDocsQuery(), Occur.MUST, new CategoryPath("Publish Date/2010", '/'));
     c = FacetsCollector.create(fsp, searcher.getIndexReader(), taxoReader);
     searcher.search(q2, c);
     results = c.getFacetResults();