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();