Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id CD3C2200BF1 for ; Mon, 19 Dec 2016 13:51:49 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id CBEF5160B35; Mon, 19 Dec 2016 12:51:49 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id E8214160B21 for ; Mon, 19 Dec 2016 13:51:48 +0100 (CET) Received: (qmail 35814 invoked by uid 500); 19 Dec 2016 12:51:46 -0000 Mailing-List: contact commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@lucene.apache.org Delivered-To: mailing list commits@lucene.apache.org Received: (qmail 34741 invoked by uid 99); 19 Dec 2016 12:51:46 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 19 Dec 2016 12:51:46 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 0881DDFBAD; Mon, 19 Dec 2016 12:51:46 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ab@apache.org To: commits@lucene.apache.org Date: Mon, 19 Dec 2016 12:51:59 -0000 Message-Id: In-Reply-To: <47362cdabf074ea79caa619569a24165@git.apache.org> References: <47362cdabf074ea79caa619569a24165@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [15/23] lucene-solr:feature/metrics: LUCENE-7587: add helper FacetQuery and MultiFacetQuery classes to simplify drill down implementation archived-at: Mon, 19 Dec 2016 12:51:50 -0000 LUCENE-7587: add helper FacetQuery and MultiFacetQuery classes to simplify drill down implementation Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/835296f2 Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/835296f2 Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/835296f2 Branch: refs/heads/feature/metrics Commit: 835296f20a17c12c66b4f043074c94e3ddd5c2b5 Parents: 3b182aa Author: Mike McCandless Authored: Fri Dec 16 09:56:51 2016 -0500 Committer: Mike McCandless Committed: Fri Dec 16 09:56:51 2016 -0500 ---------------------------------------------------------------------- lucene/CHANGES.txt | 4 + .../org/apache/lucene/facet/FacetQuery.java | 52 +++++++++++ .../apache/lucene/facet/MultiFacetQuery.java | 61 ++++++++++++ .../org/apache/lucene/facet/TestFacetQuery.java | 98 ++++++++++++++++++++ 4 files changed, 215 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/835296f2/lucene/CHANGES.txt ---------------------------------------------------------------------- diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 7e61469..47cd6e8 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -74,6 +74,10 @@ New features * LUCENE-7590: Added DocValuesStatsCollector to compute statistics on DocValues fields. (Shai Erera) +* LUCENE-7587: The new FacetQuery and MultiFacetQuery helper classes + make it simpler to execute drill down when drill sideways counts are + not needed (Emmanuel Keller via Mike McCandless) + Bug Fixes * LUCENE-7547: JapaneseTokenizerFactory was failing to close the http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/835296f2/lucene/facet/src/java/org/apache/lucene/facet/FacetQuery.java ---------------------------------------------------------------------- diff --git a/lucene/facet/src/java/org/apache/lucene/facet/FacetQuery.java b/lucene/facet/src/java/org/apache/lucene/facet/FacetQuery.java new file mode 100644 index 0000000..ec20292 --- /dev/null +++ b/lucene/facet/src/java/org/apache/lucene/facet/FacetQuery.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.lucene.facet; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; + +/** + * A term {@link Query} over a {@link FacetField}. + *

+ * NOTE:This helper class is an alternative to {@link DrillDownQuery} + * especially in cases where you don't intend to use {@link DrillSideways} + * + * @lucene.experimental + */ +public class FacetQuery extends TermQuery { + + /** + * Creates a new {@code FacetQuery} filtering the query on the given dimension. + */ + public FacetQuery(final FacetsConfig facetsConfig, final String dimension, final String... path) { + super(toTerm(facetsConfig.getDimConfig(dimension), dimension, path)); + } + + /** + * Creates a new {@code FacetQuery} filtering the query on the given dimension. + *

+ * NOTE:Uses FacetsConfig.DEFAULT_DIM_CONFIG. + */ + public FacetQuery(final String dimension, final String... path) { + super(toTerm(FacetsConfig.DEFAULT_DIM_CONFIG, dimension, path)); + } + + static Term toTerm(final FacetsConfig.DimConfig dimConfig, final String dimension, final String... path) { + return new Term(dimConfig.indexFieldName, FacetsConfig.pathToString(dimension, path)); + } +} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/835296f2/lucene/facet/src/java/org/apache/lucene/facet/MultiFacetQuery.java ---------------------------------------------------------------------- diff --git a/lucene/facet/src/java/org/apache/lucene/facet/MultiFacetQuery.java b/lucene/facet/src/java/org/apache/lucene/facet/MultiFacetQuery.java new file mode 100644 index 0000000..dd212c6 --- /dev/null +++ b/lucene/facet/src/java/org/apache/lucene/facet/MultiFacetQuery.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.lucene.facet; + +import org.apache.lucene.index.Term; +import org.apache.lucene.queries.TermsQuery; +import org.apache.lucene.search.Query; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * A multi-terms {@link Query} over a {@link FacetField}. + *

+ * NOTE:This helper class is an alternative to {@link DrillDownQuery} + * especially in cases where you don't intend to use {@link DrillSideways} + * + * @lucene.experimental + * @see org.apache.lucene.queries.TermsQuery + */ +public class MultiFacetQuery extends TermsQuery { + + /** + * Creates a new {@code MultiFacetQuery} filtering the query on the given dimension. + */ + public MultiFacetQuery(final FacetsConfig facetsConfig, final String dimension, final String[]... paths) { + super(toTerms(facetsConfig.getDimConfig(dimension), dimension, paths)); + } + + /** + * Creates a new {@code MultiFacetQuery} filtering the query on the given dimension. + *

+ * NOTE:Uses FacetsConfig.DEFAULT_DIM_CONFIG. + */ + public MultiFacetQuery(final String dimension, final String[]... paths) { + super(toTerms(FacetsConfig.DEFAULT_DIM_CONFIG, dimension, paths)); + } + + static Collection toTerms(final FacetsConfig.DimConfig dimConfig, final String dimension, + final String[]... paths) { + final Collection terms = new ArrayList<>(paths.length); + for (String[] path : paths) + terms.add(FacetQuery.toTerm(dimConfig, dimension, path)); + return terms; + } + +} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/835296f2/lucene/facet/src/test/org/apache/lucene/facet/TestFacetQuery.java ---------------------------------------------------------------------- diff --git a/lucene/facet/src/test/org/apache/lucene/facet/TestFacetQuery.java b/lucene/facet/src/test/org/apache/lucene/facet/TestFacetQuery.java new file mode 100644 index 0000000..f3aa079 --- /dev/null +++ b/lucene/facet/src/test/org/apache/lucene/facet/TestFacetQuery.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.lucene.facet; + +import org.apache.lucene.analysis.MockAnalyzer; +import org.apache.lucene.analysis.MockTokenizer; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.TextField; +import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetField; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.TopDocs; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.IOUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; + +public class TestFacetQuery extends FacetTestCase { + + private static Directory indexDirectory; + private static RandomIndexWriter indexWriter; + private static IndexReader indexReader; + private static IndexSearcher searcher; + private static FacetsConfig config; + + private static final IndexableField[] DOC_SINGLEVALUED = + new IndexableField[] { new SortedSetDocValuesFacetField("Author", "Mark Twain") }; + + private static final IndexableField[] DOC_MULTIVALUED = + new SortedSetDocValuesFacetField[] { new SortedSetDocValuesFacetField("Author", "Kurt Vonnegut") }; + + private static final IndexableField[] DOC_NOFACET = + new IndexableField[] { new TextField("Hello", "World", Field.Store.YES) }; + + @BeforeClass + public static void createTestIndex() throws IOException { + indexDirectory = newDirectory(); + // create and open an index writer + indexWriter = new RandomIndexWriter(random(), indexDirectory, + newIndexWriterConfig(new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false))); + + config = new FacetsConfig(); + + indexDocuments(DOC_SINGLEVALUED, DOC_MULTIVALUED, DOC_NOFACET); + + indexReader = indexWriter.getReader(); + // prepare searcher to search against + searcher = newSearcher(indexReader); + } + + private static void indexDocuments(IndexableField[]... docs) throws IOException { + for (IndexableField[] fields : docs) { + for (IndexableField field : fields) { + Document doc = new Document(); + doc.add(field); + indexWriter.addDocument(config.build(doc)); + } + } + } + + @AfterClass + public static void closeTestIndex() throws IOException { + IOUtils.close(indexReader, indexWriter, indexDirectory); + } + + @Test + public void testSingleValued() throws Exception { + TopDocs topDocs = searcher.search(new FacetQuery("Author", "Mark Twain"), 10); + assertEquals(1, topDocs.totalHits); + } + + @Test + public void testMultiValued() throws Exception { + TopDocs topDocs = searcher.search( + new MultiFacetQuery("Author", new String[] { "Mark Twain" }, new String[] { "Kurt Vonnegut" }), 10); + assertEquals(2, topDocs.totalHits); + } +}