Index: lucene/build.xml =================================================================== --- lucene/build.xml (revision 1440418) +++ lucene/build.xml (working copy) @@ -191,8 +191,7 @@ - - + Index: lucene/demo/build.xml =================================================================== --- lucene/demo/build.xml (revision 1440418) +++ lucene/demo/build.xml (working copy) @@ -33,20 +33,22 @@ + - + + - + @@ -63,6 +65,7 @@ + Index: lucene/demo/src/java/org/apache/lucene/facet/ExampleResult.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/ExampleResult.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/ExampleResult.java (working copy) @@ -0,0 +1,49 @@ +package org.apache.lucene.facet; + +import java.util.List; + +import org.apache.lucene.facet.search.results.FacetResult; + +/* + * 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. + */ + +/** + * Result of running an example program. + * This is a general object for allowing to write a test + * that runs an example and verifies its results. + * + * @lucene.experimental + */ +public class ExampleResult { + + private List facetResults; + + /** + * @return the facet results + */ + public List getFacetResults() { + return facetResults; + } + + /** + * @param facetResults the facet results to set + */ + public void setFacetResults(List facetResults) { + this.facetResults = facetResults; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/ExampleResult.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/ExampleUtils.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/ExampleUtils.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/ExampleUtils.java (working copy) @@ -0,0 +1,38 @@ +package org.apache.lucene.facet; + +import org.apache.lucene.util.Version; + +/* + * 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. + */ + +/** + * @lucene.experimental + */ +public class ExampleUtils { + + public static final boolean VERBOSE = Boolean.getBoolean("tests.verbose"); + + /** The Lucene {@link Version} used by the example code. */ + public static final Version EXAMPLE_VER = Version.LUCENE_40; + + public static void log(Object msg) { + if (VERBOSE) { + System.out.println(msg.toString()); + } + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/ExampleUtils.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveMain.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveMain.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveMain.java (working copy) @@ -0,0 +1,67 @@ +package org.apache.lucene.facet.adaptive; + +import java.util.List; + +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; + +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.search.AdaptiveFacetsAccumulator; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.simple.SimpleIndexer; +import org.apache.lucene.facet.simple.SimpleSearcher; + +/* + * 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. + */ + +/** + * Driver for the adaptive sample, using the {@link AdaptiveFacetsAccumulator}. + * Indexing is the same as in {@link SimpleSearcher} + * + * @lucene.experimental + */ +public class AdaptiveMain { + + /** + * Driver for the adaptive sample. + * @throws Exception on error (no detailed exception handling here for sample simplicity + */ + public static void main(String[] args) throws Exception { + new AdaptiveMain().runSample(); + ExampleUtils.log("DONE"); + } + + public ExampleResult runSample() throws Exception { + + // create Directories for the search index and for the taxonomy index + Directory indexDir = new RAMDirectory(); + Directory taxoDir = new RAMDirectory(); + + // index the sample documents + ExampleUtils.log("index the adaptive sample documents..."); + SimpleIndexer.index(indexDir, taxoDir); + + ExampleUtils.log("search the adaptive sample documents..."); + List facetRes = AdaptiveSearcher.searchWithFacets(indexDir, taxoDir); + + ExampleResult res = new ExampleResult(); + res.setFacetResults(facetRes); + return res; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveMain.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveSearcher.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveSearcher.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveSearcher.java (working copy) @@ -0,0 +1,103 @@ +package org.apache.lucene.facet.adaptive; + +import java.util.List; + +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.search.AdaptiveFacetsAccumulator; +import org.apache.lucene.facet.search.ScoredDocIdCollector; +import org.apache.lucene.facet.search.params.CountFacetRequest; +import org.apache.lucene.facet.search.params.FacetSearchParams; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.simple.SimpleUtils; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyReader; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MultiCollector; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.TopScoreDocCollector; +import org.apache.lucene.store.Directory; + +/* + * 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. + */ + +/** + * Search with facets through the {@link AdaptiveFacetsAccumulator} + * + * @lucene.experimental + */ +public class AdaptiveSearcher { + + /** + * Search with facets through the {@link AdaptiveFacetsAccumulator} + * @param indexDir Directory of the search index. + * @param taxoDir Directory of the taxonomy index. + * @throws Exception on error (no detailed exception handling here for sample simplicity + * @return facet results + */ + public static List searchWithFacets (Directory indexDir, Directory taxoDir) throws Exception { + // prepare index reader and taxonomy. + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); + IndexReader indexReader = DirectoryReader.open(indexDir); + + // prepare searcher to search against + IndexSearcher searcher = new IndexSearcher(indexReader); + + // faceted search is working in 2 steps: + // 1. collect matching documents + // 2. aggregate facets for collected documents and + // generate the requested faceted results from the aggregated facets + + // step 1: collect matching documents into a collector + Query q = new TermQuery(new Term(SimpleUtils.TEXT,"white")); + ExampleUtils.log("Query: "+q); + + // regular collector for scoring matched documents + TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(10, true); + + // docids collector for guiding facets accumulation (scoring disabled) + ScoredDocIdCollector docIdsCollecor = ScoredDocIdCollector.create(indexReader.maxDoc(), false); + + // Faceted search parameters indicate which facets are we interested in + FacetSearchParams facetSearchParams = new FacetSearchParams( + new CountFacetRequest(new CategoryPath("root", "a"), 10)); + + // search, into both collectors. note: in case only facets accumulation + // is required, the topDocCollector part can be totally discarded + searcher.search(q, MultiCollector.wrap(topDocsCollector, docIdsCollecor)); + + // Obtain facets results and print them + AdaptiveFacetsAccumulator accumulator = new AdaptiveFacetsAccumulator(facetSearchParams, indexReader, taxo); + List res = accumulator.accumulate(docIdsCollecor.getScoredDocIDs()); + + int i = 0; + for (FacetResult facetResult : res) { + ExampleUtils.log("Res "+(i++)+": "+facetResult); + } + + // we're done, close the index reader and the taxonomy. + indexReader.close(); + taxo.close(); + + return res; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/adaptive/AdaptiveSearcher.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/adaptive/package.html =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/adaptive/package.html (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/adaptive/package.html (working copy) @@ -0,0 +1,22 @@ + + + + +Facets example code for using AdaptiveFacetsAccumulator. + + Property changes on: lucene/demo/src/java/org/apache/lucene/facet/adaptive/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsIndexer.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsIndexer.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsIndexer.java (working copy) @@ -0,0 +1,119 @@ +package org.apache.lucene.facet.association; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.TextField; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.associations.AssociationsFacetFields; +import org.apache.lucene.facet.associations.CategoryAssociation; +import org.apache.lucene.facet.associations.CategoryAssociationsContainer; +import org.apache.lucene.facet.simple.SimpleUtils; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyWriter; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.IndexWriterConfig.OpenMode; +import org.apache.lucene.store.Directory; + +/* + * 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. + */ + +/** + * Sample indexer creates an index, and adds to it sample documents with + * categories, which can be simple or contain associations. + * + * @lucene.experimental + */ +public class CategoryAssociationsIndexer { + + /** + * Create an index, and adds to it sample documents and categories. + * + * @param indexDir + * Directory in which the index should be created. + * @param taxoDir + * Directory in which the taxonomy index should be created. + * @throws Exception + * on error (no detailed exception handling here for sample + * simplicity + */ + public static void index(Directory indexDir, Directory taxoDir) throws Exception { + + // create and open an index writer + IndexWriter iw = new IndexWriter(indexDir, new IndexWriterConfig(ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer)); + + // create and open a taxonomy writer + TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); + + AssociationsFacetFields assocFacetFields = new AssociationsFacetFields(taxo); + + // loop over sample documents + int nDocsAdded = 0; + int nFacetsAdded = 0; + for (int docNum = 0; docNum < SimpleUtils.docTexts.length; docNum++) { + ExampleUtils.log(" ++++ DOC ID: " + docNum); + // obtain the sample categories for current document + CategoryAssociationsContainer associations = new CategoryAssociationsContainer(); + for (CategoryPath path : SimpleUtils.categories[docNum]) { + associations.setAssociation(path, null); + ExampleUtils.log("\t ++++ PATH: " + path); + ++nFacetsAdded; + } + // and also those with associations + CategoryPath[] associationsPaths = CategoryAssociationsUtils.categories[docNum]; + CategoryAssociation[] associationsValues = CategoryAssociationsUtils.associations[docNum]; + for (int i = 0; i < associationsPaths.length; i++) { + associations.setAssociation(associationsPaths[i], associationsValues[i]); + ExampleUtils.log("\t $$$$ Association: (" + associationsPaths[i] + "," + associationsValues[i] + ")"); + ++nFacetsAdded; + } + + // create a plain Lucene document and add some regular Lucene fields + // to it + Document doc = new Document(); + doc.add(new TextField(SimpleUtils.TITLE, SimpleUtils.docTitles[docNum], Field.Store.YES)); + doc.add(new TextField(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum], Field.Store.NO)); + + // invoke the category document builder for adding categories to the + // document and, as required, to the taxonomy index + assocFacetFields.addFields(doc, associations); + + // finally add the document to the index + iw.addDocument(doc); + + nDocsAdded++; + } + + // commit changes. + // we commit changes to the taxonomy index prior to committing them to + // the search index. + // this is important, so that all facets referred to by documents in the + // search index + // will indeed exist in the taxonomy index. + taxo.commit(); + iw.commit(); + + // close the taxonomy index and the index - all modifications are + // now safely in the provided directories: indexDir and taxoDir. + taxo.close(); + iw.close(); + + ExampleUtils.log("Indexed " + nDocsAdded + " documents with overall " + nFacetsAdded + " facets."); + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsIndexer.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsMain.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsMain.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsMain.java (working copy) @@ -0,0 +1,82 @@ +package org.apache.lucene.facet.association; + +import java.util.List; + +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; + +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.search.results.FacetResult; + +/* + * 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. + */ + +/** + * Driver for the simple sample. + * + * @lucene.experimental + */ +public class CategoryAssociationsMain { + + /** + * Driver for the simple sample. + * @throws Exception on error (no detailed exception handling here for sample simplicity + */ + public static void main(String[] args) throws Exception { + new CategoryAssociationsMain().runSumIntAssociationSample(); + new CategoryAssociationsMain().runSumFloatAssociationSample(); + ExampleUtils.log("DONE"); + } + + public ExampleResult runSumIntAssociationSample() throws Exception { + + // create Directories for the search index and for the taxonomy index + Directory indexDir = new RAMDirectory();//FSDirectory.open(new File("/tmp/111")); + Directory taxoDir = new RAMDirectory(); + + // index the sample documents + ExampleUtils.log("index the sample documents..."); + CategoryAssociationsIndexer.index(indexDir, taxoDir); + + ExampleUtils.log("search the sample documents..."); + List facetRes = CategoryAssociationsSearcher.searchSumIntAssociation(indexDir, taxoDir); + + ExampleResult res = new ExampleResult(); + res.setFacetResults(facetRes); + return res; + } + + public ExampleResult runSumFloatAssociationSample() throws Exception { + + // create Directories for the search index and for the taxonomy index + Directory indexDir = new RAMDirectory();//FSDirectory.open(new File("/tmp/111")); + Directory taxoDir = new RAMDirectory(); + + // index the sample documents + ExampleUtils.log("index the sample documents..."); + CategoryAssociationsIndexer.index(indexDir, taxoDir); + + ExampleUtils.log("search the sample documents..."); + List facetRes = CategoryAssociationsSearcher.searchSumFloatAssociation(indexDir, taxoDir); + + ExampleResult res = new ExampleResult(); + res.setFacetResults(facetRes); + return res; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsMain.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsSearcher.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsSearcher.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsSearcher.java (working copy) @@ -0,0 +1,75 @@ +package org.apache.lucene.facet.association; + +import java.util.List; + +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.store.Directory; + +import org.apache.lucene.facet.search.params.associations.AssociationFloatSumFacetRequest; +import org.apache.lucene.facet.search.params.associations.AssociationIntSumFacetRequest; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.simple.SimpleSearcher; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyReader; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; + +/* + * 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. + */ + +/** + * AssociationSearcher searches index with facets, evaluating the facets with + * their associated $int value + * + * @lucene.experimental + */ +public class CategoryAssociationsSearcher { + + /** Search an index with a sum of int-association. */ + public static List searchSumIntAssociation(Directory indexDir, Directory taxoDir) throws Exception { + // prepare index reader + IndexReader indexReader = DirectoryReader.open(indexDir); + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); + + AssociationIntSumFacetRequest facetRequest = new AssociationIntSumFacetRequest(new CategoryPath("tags"), 10); + List res = SimpleSearcher.searchWithRequest(indexReader, taxo, null, facetRequest); + + // close readers + taxo.close(); + indexReader.close(); + + return res; + } + + /** Search an index with a sum of float-association. */ + public static List searchSumFloatAssociation(Directory indexDir, Directory taxoDir) throws Exception { + // prepare index reader + IndexReader indexReader = DirectoryReader.open(indexDir); + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); + + AssociationFloatSumFacetRequest facetRequest = new AssociationFloatSumFacetRequest(new CategoryPath("genre"), 10); + + List res = SimpleSearcher.searchWithRequest(indexReader, taxo, null, facetRequest); + + // close readers + taxo.close(); + indexReader.close(); + + return res; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsSearcher.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsUtils.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsUtils.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsUtils.java (working copy) @@ -0,0 +1,70 @@ +package org.apache.lucene.facet.association; + +import org.apache.lucene.facet.associations.CategoryAssociation; +import org.apache.lucene.facet.associations.CategoryFloatAssociation; +import org.apache.lucene.facet.associations.CategoryIntAssociation; +import org.apache.lucene.facet.taxonomy.CategoryPath; + +/* + * 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. + */ + +/** + * @lucene.experimental + */ +public class CategoryAssociationsUtils { + + /** + * Categories: categories[D][N] == category-path with association no. N for + * document no. D. + */ + public static CategoryPath[][] categories = { + // Doc #1 + { new CategoryPath("tags", "lucene") , + new CategoryPath("genre", "computing") + }, + + // Doc #2 + { new CategoryPath("tags", "lucene"), + new CategoryPath("tags", "solr"), + new CategoryPath("genre", "computing"), + new CategoryPath("genre", "software") + } + }; + + public static CategoryAssociation[][] associations = { + // Doc #1 associations + { + /* 3 occurrences for tag 'lucene' */ + new CategoryIntAssociation(3), + /* 87% confidence level of genre 'computing' */ + new CategoryFloatAssociation(0.87f) + }, + + // Doc #2 associations + { + /* 1 occurrence for tag 'lucene' */ + new CategoryIntAssociation(1), + /* 2 occurrences for tag 'solr' */ + new CategoryIntAssociation(2), + /* 75% confidence level of genre 'computing' */ + new CategoryFloatAssociation(0.75f), + /* 34% confidence level of genre 'software' */ + new CategoryFloatAssociation(0.34f), + } + }; + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/association/CategoryAssociationsUtils.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/association/package.html =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/association/package.html (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/association/package.html (working copy) @@ -0,0 +1,22 @@ + + + + +Facets example code for using associations. + + Property changes on: lucene/demo/src/java/org/apache/lucene/facet/association/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLIndexer.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLIndexer.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLIndexer.java (working copy) @@ -0,0 +1,206 @@ +package org.apache.lucene.facet.multiCL; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.TextField; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.index.FacetFields; +import org.apache.lucene.facet.index.params.CategoryListParams; +import org.apache.lucene.facet.index.params.FacetIndexingParams; +import org.apache.lucene.facet.index.params.PerDimensionIndexingParams; +import org.apache.lucene.facet.simple.SimpleUtils; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.IndexWriterConfig.OpenMode; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; + +/* + * 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. + */ + +/** + * Sample indexer creates an index, and adds to it sample documents and facets + * with multiple CategoryLists specified for different facets, so there are different + * category lists for different facets. + * + * @lucene.experimental + */ +public class MultiCLIndexer { + + // Number of documents to index + public static int NUM_DOCS = 100; + // Number of facets to add per document + public static int NUM_FACETS_PER_DOC = 10; + // Number of tokens in title + public static int TITLE_LENGTH = 5; + // Number of tokens in text + public static int TEXT_LENGTH = 100; + + // Lorum ipsum to use as content - this will be tokenized and used for document + // titles/text. + static String words = "Sed ut perspiciatis unde omnis iste natus error sit " + + "voluptatem accusantium doloremque laudantium totam rem aperiam " + + "eaque ipsa quae ab illo inventore veritatis et quasi architecto " + + "beatae vitae dicta sunt explicabo Nemo enim ipsam voluptatem " + + "quia voluptas sit aspernatur aut odit aut fugit sed quia consequuntur " + + "magni dolores eos qui ratione voluptatem sequi nesciunt Neque porro " + + "quisquam est qui dolorem ipsum quia dolor sit amet consectetur adipisci velit " + + "sed quia non numquam eius modi tempora incidunt ut labore et dolore " + + "magnam aliquam quaerat voluptatem Ut enim ad minima veniam " + + "quis nostrum exercitationem ullam corporis suscipit laboriosam " + + "nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure" + + "reprehenderit qui in ea voluptate velit esse quam nihil molestiae " + + "consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur"; + // PerDimensionIndexingParams for multiple category lists + public static final PerDimensionIndexingParams MULTI_IPARAMS; + + // Initialize PerDimensionIndexingParams + static { + Map paramsMap = new HashMap(); + paramsMap.put(new CategoryPath("0"), new CategoryListParams("$Digits$Zero")); + paramsMap.put(new CategoryPath("1"), new CategoryListParams("$Digits$One")); + paramsMap.put(new CategoryPath("2"), new CategoryListParams("$Digits$Two")); + paramsMap.put(new CategoryPath("3"), new CategoryListParams("$Digits$Three")); + paramsMap.put(new CategoryPath("4"), new CategoryListParams("$Digits$Four")); + paramsMap.put(new CategoryPath("5"), new CategoryListParams("$Digits$Five")); + MULTI_IPARAMS = new PerDimensionIndexingParams(paramsMap); + } + + /** + * Create an index, and adds to it sample documents and facets. + * + * @param indexDir + * Directory in which the index should be created. + * @param taxoDir + * Directory in which the taxonomy index should be created. + * @throws Exception + * on error (no detailed exception handling here for sample + * simplicity + */ + public static void index(Directory indexDir, Directory taxoDir) throws Exception { + + Random random = new Random(2003); + + String[] docTitles = new String[NUM_DOCS]; + String[] docTexts = new String[NUM_DOCS]; + CategoryPath[][] cPaths = new CategoryPath[NUM_DOCS][NUM_FACETS_PER_DOC]; + + String[] tokens = words.split(" "); + for (int docNum = 0; docNum < NUM_DOCS; docNum++) { + String title = ""; + String text = ""; + for (int j = 0; j < TITLE_LENGTH; j++) { + title = title + tokens[random.nextInt(tokens.length)] + " "; + } + docTitles[docNum] = title; + + for (int j = 0; j < TEXT_LENGTH; j++) { + text = text + tokens[random.nextInt(tokens.length)] + " "; + } + docTexts[docNum] = text; + + for (int facetNum = 0; facetNum < NUM_FACETS_PER_DOC; facetNum++) { + cPaths[docNum][facetNum] = new CategoryPath(Integer + .toString(random.nextInt(7)), Integer.toString(random.nextInt(10))); + } + } + index(indexDir, taxoDir, MULTI_IPARAMS, docTitles, docTexts, cPaths); + } + + /** + * More advanced method for specifying custom indexing params, doc texts, + * doc titles and category paths. + */ + public static void index(Directory indexDir, Directory taxoDir, + FacetIndexingParams iParams, String[] docTitles, + String[] docTexts, CategoryPath[][] cPaths) throws Exception { + // create and open an index writer + IndexWriter iw = new IndexWriter(indexDir, new IndexWriterConfig( + ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer).setOpenMode(OpenMode.CREATE)); + // create and open a taxonomy writer + DirectoryTaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); + index(iw, taxo, iParams, docTitles, docTexts, cPaths); + } + + /** + * More advanced method for specifying custom indexing params, doc texts, + * doc titles and category paths. + *

+ * Create an index, and adds to it sample documents and facets. + * @throws Exception + * on error (no detailed exception handling here for sample + * simplicity + */ + public static void index(IndexWriter iw, DirectoryTaxonomyWriter taxo, + FacetIndexingParams iParams, String[] docTitles, + String[] docTexts, CategoryPath[][] cPaths) throws Exception { + + // loop over sample documents + int nDocsAdded = 0; + int nFacetsAdded = 0; + for (int docNum = 0; docNum < SimpleUtils.docTexts.length; docNum++) { + List facetList = Arrays.asList(cPaths[docNum]); + + // we do not alter indexing parameters! + // FacetFields adds the categories to the document in addFields() + FacetFields facetFields = new FacetFields(taxo, iParams); + + // create a plain Lucene document and add some regular Lucene fields + // to it + Document doc = new Document(); + doc.add(new TextField(SimpleUtils.TITLE, docTitles[docNum], Field.Store.YES)); + doc.add(new TextField(SimpleUtils.TEXT, docTexts[docNum], Field.Store.NO)); + + // finally add the document to the index + facetFields.addFields(doc, facetList); + iw.addDocument(doc); + + nDocsAdded++; + nFacetsAdded += facetList.size(); + } + + // commit changes. + // we commit changes to the taxonomy index prior to committing them to + // the search index. + // this is important, so that all facets referred to by documents in the + // search index + // will indeed exist in the taxonomy index. + taxo.commit(); + iw.commit(); + + // close the taxonomy index and the index - all modifications are + // now safely in the provided directories: indexDir and taxoDir. + taxo.close(); + iw.close(); + + ExampleUtils.log("Indexed " + nDocsAdded + " documents with overall " + + nFacetsAdded + " facets."); + } + + public static void main(String[] args) throws Exception { + index(new RAMDirectory(), new RAMDirectory()); + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLIndexer.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLMain.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLMain.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLMain.java (working copy) @@ -0,0 +1,65 @@ +package org.apache.lucene.facet.multiCL; + +import java.util.List; + +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; + +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.search.results.FacetResult; + +/* + * 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. + */ + +/** + * @lucene.experimental + */ +public class MultiCLMain { + + /** + * Driver for the multi sample. + * + * @throws Exception + * on error (no detailed exception handling here for sample + * simplicity + */ + public static void main(String[] args) throws Exception { + new MultiCLMain().runSample(); + ExampleUtils.log("DONE"); + } + + public ExampleResult runSample() throws Exception { + + // create Directories for the search index and for the taxonomy index + Directory indexDir = new RAMDirectory(); + Directory taxoDir = new RAMDirectory(); + + // index the sample documents + ExampleUtils.log("index the sample documents..."); + MultiCLIndexer.index(indexDir, taxoDir); + + ExampleUtils.log("search the sample documents..."); + List facetRes = MultiCLSearcher.searchWithFacets(indexDir, + taxoDir, MultiCLIndexer.MULTI_IPARAMS); + + ExampleResult res = new ExampleResult(); + res.setFacetResults(facetRes); + return res; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLMain.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLSearcher.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLSearcher.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLSearcher.java (working copy) @@ -0,0 +1,127 @@ +package org.apache.lucene.facet.multiCL; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.TopScoreDocCollector; +import org.apache.lucene.store.Directory; + +import org.apache.lucene.search.MultiCollector; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.index.params.FacetIndexingParams; +import org.apache.lucene.facet.search.FacetsCollector; +import org.apache.lucene.facet.search.params.CountFacetRequest; +import org.apache.lucene.facet.search.params.FacetRequest; +import org.apache.lucene.facet.search.params.FacetSearchParams; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.simple.SimpleUtils; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyReader; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; + +/* + * 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. + */ + +/** + * MultiSearcher searches index with facets over an index with multiple + * category lists. + * + * @lucene.experimental + */ +public class MultiCLSearcher { + + /** + * Search an index with facets. + * + * @param indexDir + * Directory of the search index. + * @param taxoDir + * Directory of the taxonomy index. + * @throws Exception + * on error (no detailed exception handling here for sample + * simplicity + * @return facet results + */ + public static List searchWithFacets(Directory indexDir, + Directory taxoDir, FacetIndexingParams iParams) throws Exception { + + // prepare index reader and taxonomy. + IndexReader indexReader = DirectoryReader.open(indexDir); + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); + + // Get results + List results = searchWithFacets(indexReader, taxo, iParams); + + // we're done, close the index reader and the taxonomy. + indexReader.close(); + taxo.close(); + return results; + } + + public static List searchWithFacets(IndexReader indexReader, + TaxonomyReader taxo, FacetIndexingParams iParams) throws Exception { + // prepare searcher to search against + IndexSearcher searcher = new IndexSearcher(indexReader); + + // faceted search is working in 2 steps: + // 1. collect matching documents + // 2. aggregate facets for collected documents and + // generate the requested faceted results from the aggregated facets + + // step 1: create a query for finding matching documents for which we + // accumulate facets + Query q = new TermQuery(new Term(SimpleUtils.TEXT, "Quis")); + ExampleUtils.log("Query: " + q); + + TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(10, true); + + // Faceted search parameters indicate which facets are we interested in + List facetRequests = new ArrayList(); + facetRequests.add(new CountFacetRequest(new CategoryPath("5"), 10)); + facetRequests.add(new CountFacetRequest(new CategoryPath("5", "5"), 10)); + facetRequests.add(new CountFacetRequest(new CategoryPath("6", "2"), 10)); + FacetSearchParams facetSearchParams = new FacetSearchParams(facetRequests, iParams); + + // Facets collector is the simplest interface for faceted search. + // It provides faceted search functions that are sufficient to many + // application, + // although it is insufficient for tight control on faceted search + // behavior - in those + // situations other, more low-level interfaces are available, as + // demonstrated in other search examples. + FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, indexReader, taxo); + + // perform documents search and facets accumulation + searcher.search(q, MultiCollector.wrap(topDocsCollector, facetsCollector)); + + // Obtain facets results and print them + List res = facetsCollector.getFacetResults(); + + int i = 0; + for (FacetResult facetResult : res) { + ExampleUtils.log("Res " + (i++) + ": " + facetResult); + } + return res; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/multiCL/MultiCLSearcher.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/multiCL/package.html =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/multiCL/package.html (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/multiCL/package.html (working copy) @@ -0,0 +1,22 @@ + + + + +Facets example code for using multiple category lists. + + Property changes on: lucene/demo/src/java/org/apache/lucene/facet/multiCL/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/package.html =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/package.html (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/package.html (working copy) @@ -0,0 +1,22 @@ + + + + +Facets example code. + + Property changes on: lucene/demo/src/java/org/apache/lucene/facet/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleIndexer.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleIndexer.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleIndexer.java (working copy) @@ -0,0 +1,98 @@ +package org.apache.lucene.facet.simple; + +import java.util.Arrays; +import java.util.List; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.TextField; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.index.FacetFields; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyWriter; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.IndexWriterConfig.OpenMode; +import org.apache.lucene.store.Directory; + +/* + * 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. + */ + +/** + * Sample indexer creates an index, and adds to it sample documents and facets. + * + * @lucene.experimental + */ +public class SimpleIndexer { + + /** + * Create an index, and adds to it sample documents and facets. + * @param indexDir Directory in which the index should be created. + * @param taxoDir Directory in which the taxonomy index should be created. + * @throws Exception on error (no detailed exception handling here for sample simplicity + */ + public static void index (Directory indexDir, Directory taxoDir) throws Exception { + + // create and open an index writer + final IndexWriter iw = new IndexWriter(indexDir, + new IndexWriterConfig(ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer)); + + // create and open a taxonomy writer + final TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); + + // FacetFields adds the categories to the document in addFields() + final FacetFields facetFields = new FacetFields(taxo); + + // loop over sample documents + int nDocsAdded = 0; + int nFacetsAdded = 0; + for (int docNum = 0; docNum < SimpleUtils.docTexts.length; docNum++) { + // obtain the sample facets for current document + List facetList = Arrays.asList(SimpleUtils.categories[docNum]); + + // create a plain Lucene document and add some regular Lucene fields to it + Document doc = new Document(); + doc.add(new TextField(SimpleUtils.TITLE, SimpleUtils.docTitles[docNum], Field.Store.YES)); + doc.add(new TextField(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum], Field.Store.NO)); + + // add the facet fields to the document + facetFields.addFields(doc, facetList); + + // finally add the document to the index + iw.addDocument(doc); + + nDocsAdded ++; + nFacetsAdded += facetList.size(); + } + + // commit changes. + // we commit changes to the taxonomy index prior to committing them to the search index. + // this is important, so that all facets referred to by documents in the search index + // will indeed exist in the taxonomy index. + taxo.commit(); + iw.commit(); + + // close the taxonomy index and the index - all modifications are + // now safely in the provided directories: indexDir and taxoDir. + taxo.close(); + iw.close(); + + ExampleUtils.log("Indexed "+nDocsAdded+" documents with overall "+nFacetsAdded+" facets."); + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleIndexer.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleMain.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleMain.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleMain.java (working copy) @@ -0,0 +1,100 @@ +package org.apache.lucene.facet.simple; + +import java.util.List; + +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; + +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.taxonomy.TaxonomyReader; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; + +/* + * 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. + */ + +/** + * Driver for the simple sample. + * + * @lucene.experimental + */ +public class SimpleMain { + + /** + * Driver for the simple sample. + * @throws Exception on error (no detailed exception handling here for sample simplicity + */ + public static void main(String[] args) throws Exception { + new SimpleMain().runSimple(); + new SimpleMain().runDrillDown().getFacetResults(); + ExampleUtils.log("DONE"); + } + + public ExampleResult runSimple() throws Exception { + // create Directories for the search index and for the taxonomy index + Directory indexDir = new RAMDirectory(); + Directory taxoDir = new RAMDirectory(); + + // index the sample documents + ExampleUtils.log("index the sample documents..."); + SimpleIndexer.index(indexDir, taxoDir); + + // open readers + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); + IndexReader indexReader = DirectoryReader.open(indexDir); + + ExampleUtils.log("search the sample documents..."); + List facetRes = SimpleSearcher.searchWithFacets(indexReader, taxo); + + // close readers + taxo.close(); + indexReader.close(); + + ExampleResult res = new ExampleResult(); + res.setFacetResults(facetRes); + return res; + } + + public ExampleResult runDrillDown() throws Exception { + // create Directories for the search index and for the taxonomy index + Directory indexDir = new RAMDirectory(); + Directory taxoDir = new RAMDirectory(); + + // index the sample documents + ExampleUtils.log("index the sample documents..."); + SimpleIndexer.index(indexDir, taxoDir); + + // open readers + TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); + IndexReader indexReader = DirectoryReader.open(indexDir); + + ExampleUtils.log("search the sample documents..."); + List facetRes = SimpleSearcher.searchWithDrillDown(indexReader, taxo); + + // close readers + taxo.close(); + indexReader.close(); + + ExampleResult res = new ExampleResult(); + res.setFacetResults(facetRes); + return res; + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleMain.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleSearcher.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleSearcher.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleSearcher.java (working copy) @@ -0,0 +1,164 @@ +package org.apache.lucene.facet.simple; + +import java.util.Iterator; +import java.util.List; + +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.index.params.FacetIndexingParams; +import org.apache.lucene.facet.search.DrillDown; +import org.apache.lucene.facet.search.FacetsCollector; +import org.apache.lucene.facet.search.params.CountFacetRequest; +import org.apache.lucene.facet.search.params.FacetRequest; +import org.apache.lucene.facet.search.params.FacetSearchParams; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.search.results.FacetResultNode; +import org.apache.lucene.facet.taxonomy.CategoryPath; +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; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.TopScoreDocCollector; + +/* + * 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. + */ + +/** + * SampleSearcer searches index with facets. + * + * @lucene.experimental + */ +public class SimpleSearcher { + + /** + * Search an index with facets. + * @param indexReader index reader. + * @param taxoReader taxonomy reader. + * @throws Exception on error (no detailed exception handling here for sample simplicity + * @return facet results + */ + public static List searchWithFacets (IndexReader indexReader, + TaxonomyReader taxoReader) throws Exception { + CountFacetRequest facetRequest = new CountFacetRequest(new CategoryPath("root","a"), 10); + return searchWithRequest(indexReader, taxoReader, null, facetRequest); + } + + /** + * Search an index with facets for given facet requests. + * @param indexReader index reader. + * @param taxoReader taxonomy reader. + * @param indexingParams the facet indexing params + * @param facetRequests facet requests of interest + * @throws Exception on error (no detailed exception handling here for sample simplicity + * @return facet results + */ + public static List searchWithRequest(IndexReader indexReader, + TaxonomyReader taxoReader, FacetIndexingParams indexingParams, + FacetRequest... facetRequests) throws Exception { + Query q = new TermQuery(new Term(SimpleUtils.TEXT, "white")); + return searchWithRequestAndQuery(q, indexReader, taxoReader, + indexingParams, facetRequests); + } + + /** + * Search an index with facets for given query and facet requests. + * @param q query of interest + * @param indexReader index reader. + * @param taxoReader taxonomy reader. + * @param indexingParams the facet indexing params + * @param facetRequests facet requests of interest + * @throws Exception on error (no detailed exception handling here for sample simplicity + * @return facet results + */ + public static List searchWithRequestAndQuery(Query q, + IndexReader indexReader, TaxonomyReader taxoReader, + FacetIndexingParams indexingParams, FacetRequest... facetRequests) + throws Exception { + + ExampleUtils.log("Query: " + q); + // prepare searcher to search against + IndexSearcher searcher = new IndexSearcher(indexReader); + + // collect matching documents into a collector + TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(10, true); + + if (indexingParams == null) { + indexingParams = FacetIndexingParams.ALL_PARENTS; + } + + // Faceted search parameters indicate which facets are we interested in + FacetSearchParams facetSearchParams = new FacetSearchParams(indexingParams, facetRequests); + + FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, indexReader, taxoReader); + + // perform documents search and facets accumulation + searcher.search(q, MultiCollector.wrap(topDocsCollector, facetsCollector)); + + // Obtain facets results and print them + List res = facetsCollector.getFacetResults(); + + int i = 0; + for (FacetResult facetResult : res) { + ExampleUtils.log("Res " + (i++) + ": " + facetResult); + } + + return res; + } + + /** + * Search an index with facets drill-down. + * @param indexReader index reader. + * @param taxoReader taxonomy reader. + * @throws Exception on error (no detailed exception handling here for sample simplicity + * @return facet results + */ + public static List searchWithDrillDown(IndexReader indexReader, + TaxonomyReader taxoReader) throws Exception { + + final FacetIndexingParams indexingParams = FacetIndexingParams.ALL_PARENTS; + + // base query the user is interested in + Query baseQuery = new TermQuery(new Term(SimpleUtils.TEXT, "white")); + + // facet of interest + CountFacetRequest facetRequest = new CountFacetRequest(new CategoryPath("root","a"), 10); + + // initial search - all docs matching the base query will contribute to the accumulation + List res1 = searchWithRequest(indexReader, taxoReader, indexingParams, facetRequest); + + // a single result (because there was a single request) + FacetResult fres = res1.get(0); + + // assume the user is interested in the second sub-result + // (just take the second sub-result returned by the iterator - we know there are 3 results!) + Iterator resIterator = fres.getFacetResultNode().subResults.iterator(); + resIterator.next(); // skip first result + 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, 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 + // category of interest will contribute to the new accumulation + return searchWithRequestAndQuery(q2, indexReader, taxoReader, indexingParams, facetRequest); + } + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleSearcher.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleUtils.java =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleUtils.java (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleUtils.java (working copy) @@ -0,0 +1,71 @@ +package org.apache.lucene.facet.simple; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.core.WhitespaceAnalyzer; +import org.apache.lucene.facet.ExampleUtils; +import org.apache.lucene.facet.taxonomy.CategoryPath; + +/* + * 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. + */ + +/** + * Some definitions for the Simple Sample. + * + * @lucene.experimental + */ +public class SimpleUtils { + + /** + * Documents text field. + */ + public static final String TEXT = "text"; + + /** + * Documents title field. + */ + public static final String TITLE = "title"; + + /** + * sample documents text (for the text field). + */ + public static String[] docTexts = { + "the white car is the one I want.", + "the white dog does not belong to anyone.", + }; + + /** + * sample documents titles (for the title field). + */ + public static String[] docTitles = { + "white car", + "white dog", + }; + + /** + * Categories: categories[D][N] == category-path no. N for document no. D. + */ + public static CategoryPath[][] categories = { + { new CategoryPath("root","a","f1"), new CategoryPath("root","a","f2") }, + { new CategoryPath("root","a","f1"), new CategoryPath("root","a","f3") }, + }; + + /** + * Analyzer used in the simple sample. + */ + public static final Analyzer analyzer = new WhitespaceAnalyzer(ExampleUtils.EXAMPLE_VER); + +} Property changes on: lucene/demo/src/java/org/apache/lucene/facet/simple/SimpleUtils.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/java/org/apache/lucene/facet/simple/package.html =================================================================== --- lucene/demo/src/java/org/apache/lucene/facet/simple/package.html (revision 0) +++ lucene/demo/src/java/org/apache/lucene/facet/simple/package.html (working copy) @@ -0,0 +1,22 @@ + + + + +Facets simple example code. + + Property changes on: lucene/demo/src/java/org/apache/lucene/facet/simple/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/test/org/apache/lucene/facet/TestAdaptiveExample.java =================================================================== --- lucene/demo/src/test/org/apache/lucene/facet/TestAdaptiveExample.java (revision 0) +++ lucene/demo/src/test/org/apache/lucene/facet/TestAdaptiveExample.java (working copy) @@ -0,0 +1,40 @@ +package org.apache.lucene.facet; + +import org.junit.Test; + +import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.adaptive.AdaptiveMain; + +/* + * 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. + */ + +/** + * Test that the adaptive example works as expected. This test helps to verify + * that examples code is alive! + */ +public class TestAdaptiveExample extends LuceneTestCase { + + @Test + public void testAdaptive () throws Exception { + ExampleResult res = new AdaptiveMain().runSample(); + assertNotNull("Null result!", res); + assertNotNull("Null facet result!", res.getFacetResults()); + assertEquals("Wrong number of results!",1, res.getFacetResults().size()); + assertEquals("Wrong number of facets!",3, res.getFacetResults().get(0).getNumValidDescendants()); + } +} Property changes on: lucene/demo/src/test/org/apache/lucene/facet/TestAdaptiveExample.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/test/org/apache/lucene/facet/TestAssociationExample.java =================================================================== --- lucene/demo/src/test/org/apache/lucene/facet/TestAssociationExample.java (revision 0) +++ lucene/demo/src/test/org/apache/lucene/facet/TestAssociationExample.java (working copy) @@ -0,0 +1,55 @@ +package org.apache.lucene.facet; + +import org.junit.Test; + +import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.association.CategoryAssociationsMain; +import org.apache.lucene.facet.search.results.FacetResultNode; + +/* + * 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. + */ + +/** + * Test that the association example works as expected. This test helps to + * verify that examples code is alive! + */ +public class TestAssociationExample extends LuceneTestCase { + + private static final double[] EXPECTED_INT_SUM_RESULTS = { 4, 2}; + private static final double[] EXPECTED_FLOAT_SUM_RESULTS = { 1.62, 0.34}; + + @Test + public void testAssociationExamples() throws Exception { + assertExampleResult(new CategoryAssociationsMain().runSumIntAssociationSample(), EXPECTED_INT_SUM_RESULTS); + assertExampleResult(new CategoryAssociationsMain().runSumFloatAssociationSample(), EXPECTED_FLOAT_SUM_RESULTS); + } + + private void assertExampleResult(ExampleResult res, double[] expectedResults) { + assertNotNull("Null result!", res); + assertNotNull("Null facet result!", res.getFacetResults()); + assertEquals("Wrong number of results!", 1, res.getFacetResults().size()); + assertEquals("Wrong number of facets!", 2, res.getFacetResults().get(0).getNumValidDescendants()); + + Iterable it = res.getFacetResults().get(0).getFacetResultNode().subResults; + int i = 0; + for (FacetResultNode fResNode : it) { + assertEquals("Wrong result for facet "+fResNode.label, expectedResults[i++], fResNode.value, 1E-5); + } + } + +} Property changes on: lucene/demo/src/test/org/apache/lucene/facet/TestAssociationExample.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/test/org/apache/lucene/facet/TestMultiCLExample.java =================================================================== --- lucene/demo/src/test/org/apache/lucene/facet/TestMultiCLExample.java (revision 0) +++ lucene/demo/src/test/org/apache/lucene/facet/TestMultiCLExample.java (working copy) @@ -0,0 +1,78 @@ +package org.apache.lucene.facet; + +import java.util.Iterator; +import java.util.List; + +import org.junit.Test; + +import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.multiCL.MultiCLMain; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.search.results.FacetResultNode; + +/* + * 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. + */ + +/** + * Test that the multi-category list example works as expected. This test helps + * to verify that examples code is alive! + */ +public class TestMultiCLExample extends LuceneTestCase { + + @Test + public void testMulti() throws Exception { + ExampleResult res = new MultiCLMain().runSample(); + assertCorrectMultiResults(res); + } + + public static void assertCorrectMultiResults(ExampleResult exampleResults) { + List results = exampleResults.getFacetResults(); + FacetResult result = results.get(0); + assertNotNull("Result should not be null", result); + FacetResultNode node = result.getFacetResultNode(); + assertEquals("Invalid label", "5", node.label.toString()); + assertEquals("Invalid # of subresults", 3, node.subResults.size()); + + Iterator subResults = node.subResults.iterator(); + FacetResultNode sub = subResults.next(); + assertEquals("Invalid subresult value", 1.0, sub.value, 0.0); + assertEquals("Invalid subresult label", "5/2", sub.label.toString()); + sub = subResults.next(); + assertEquals("Invalid subresult value", 1.0, sub.value, 0.0); + assertEquals("Invalid subresult label", "5/7", sub.label.toString()); + sub = subResults.next(); + assertEquals("Invalid subresult value", 1.0, sub.value, 0.0); + assertEquals("Invalid subresult label", "5/5", sub.label.toString()); + + result = results.get(1); + node = result.getFacetResultNode(); + assertNotNull("Result should not be null", result); + assertEquals("Invalid label", "5/5", node.label.toString()); + assertEquals("Invalid value", 1, node.value, 0.0); + assertEquals("Invalid number of subresults", 0, node.subResults.size()); + + result = results.get(2); + node = result.getFacetResultNode(); + assertNotNull("Result should not be null", result); + assertEquals("Invalid label", "6/2", node.label.toString()); + assertEquals("Invalid value", 1, node.value, 0.0); + assertEquals("Invalid number of subresults", 0, node.subResults.size()); + + } + +} Property changes on: lucene/demo/src/test/org/apache/lucene/facet/TestMultiCLExample.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/demo/src/test/org/apache/lucene/facet/TestSimpleExample.java =================================================================== --- lucene/demo/src/test/org/apache/lucene/facet/TestSimpleExample.java (revision 0) +++ lucene/demo/src/test/org/apache/lucene/facet/TestSimpleExample.java (working copy) @@ -0,0 +1,67 @@ +package org.apache.lucene.facet; + +import java.util.Iterator; + +import org.junit.Test; + +import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.facet.ExampleResult; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.search.results.FacetResultNode; +import org.apache.lucene.facet.simple.SimpleMain; + +/* + * 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. + */ + +/** + * Test that the simple example works as expected. This test helps to verify + * that examples code is alive! + */ +public class TestSimpleExample extends LuceneTestCase { + + @Test + public void testSimple() throws Exception { + ExampleResult res = new SimpleMain().runSimple(); + assertNotNull("Null result!", res); + assertNotNull("Null facet result!", res.getFacetResults()); + assertEquals("Wrong number of results!",1, res.getFacetResults().size()); + assertEquals("Wrong number of facets!",3, res.getFacetResults().get(0).getNumValidDescendants()); + } + + /** + * In drill down test we are drilling down to a facet that appears in a single document. + * As result, facets that without drill down got count of 2 will now get a count of 1. + */ + @Test + public void testDrillDown() throws Exception { + ExampleResult res = new SimpleMain().runDrillDown(); + assertNotNull("Null result!", res); + assertNotNull("Null facet result!", res.getFacetResults()); + assertEquals("Wrong number of results!",1, res.getFacetResults().size()); + + // drill down facet appears in only 1 doc, and that doc has only 2 facets + FacetResult facetResult = res.getFacetResults().get(0); + assertEquals("Wrong number of facets!",2, facetResult.getNumValidDescendants()); + + Iterator resIterator = facetResult.getFacetResultNode().subResults.iterator(); + assertTrue("Too few results", resIterator.hasNext()); + assertEquals("wrong count for first result out of 2", 1, (int)resIterator.next().value); + assertTrue("Too few results", resIterator.hasNext()); + assertEquals("wrong count for second result out of 2", 1, (int)resIterator.next().value); + assertFalse("Too many results!", resIterator.hasNext()); + } +} Property changes on: lucene/demo/src/test/org/apache/lucene/facet/TestSimpleExample.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/facet/build.xml =================================================================== --- lucene/facet/build.xml (revision 1440418) +++ lucene/facet/build.xml (working copy) @@ -28,52 +28,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index: lucene/facet/src/examples/org/apache/lucene/facet/example/ExampleResult.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/ExampleResult.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/ExampleResult.java (working copy) @@ -1,49 +0,0 @@ -package org.apache.lucene.facet.example; - -import java.util.List; - -import org.apache.lucene.facet.search.results.FacetResult; - -/* - * 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. - */ - -/** - * Result of running an example program. - * This is a general object for allowing to write a test - * that runs an example and verifies its results. - * - * @lucene.experimental - */ -public class ExampleResult { - - private List facetResults; - - /** - * @return the facet results - */ - public List getFacetResults() { - return facetResults; - } - - /** - * @param facetResults the facet results to set - */ - public void setFacetResults(List facetResults) { - this.facetResults = facetResults; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/ExampleUtils.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/ExampleUtils.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/ExampleUtils.java (working copy) @@ -1,38 +0,0 @@ -package org.apache.lucene.facet.example; - -import org.apache.lucene.util.Version; - -/* - * 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. - */ - -/** - * @lucene.experimental - */ -public class ExampleUtils { - - public static final boolean VERBOSE = Boolean.getBoolean("tests.verbose"); - - /** The Lucene {@link Version} used by the example code. */ - public static final Version EXAMPLE_VER = Version.LUCENE_40; - - public static void log(Object msg) { - if (VERBOSE) { - System.out.println(msg.toString()); - } - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveMain.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveMain.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveMain.java (working copy) @@ -1,67 +0,0 @@ -package org.apache.lucene.facet.example.adaptive; - -import java.util.List; - -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.RAMDirectory; - -import org.apache.lucene.facet.example.ExampleResult; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.example.simple.SimpleIndexer; -import org.apache.lucene.facet.example.simple.SimpleSearcher; -import org.apache.lucene.facet.search.AdaptiveFacetsAccumulator; -import org.apache.lucene.facet.search.results.FacetResult; - -/* - * 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. - */ - -/** - * Driver for the adaptive sample, using the {@link AdaptiveFacetsAccumulator}. - * Indexing is the same as in {@link SimpleSearcher} - * - * @lucene.experimental - */ -public class AdaptiveMain { - - /** - * Driver for the adaptive sample. - * @throws Exception on error (no detailed exception handling here for sample simplicity - */ - public static void main(String[] args) throws Exception { - new AdaptiveMain().runSample(); - ExampleUtils.log("DONE"); - } - - public ExampleResult runSample() throws Exception { - - // create Directories for the search index and for the taxonomy index - Directory indexDir = new RAMDirectory(); - Directory taxoDir = new RAMDirectory(); - - // index the sample documents - ExampleUtils.log("index the adaptive sample documents..."); - SimpleIndexer.index(indexDir, taxoDir); - - ExampleUtils.log("search the adaptive sample documents..."); - List facetRes = AdaptiveSearcher.searchWithFacets(indexDir, taxoDir); - - ExampleResult res = new ExampleResult(); - res.setFacetResults(facetRes); - return res; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveSearcher.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveSearcher.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/adaptive/AdaptiveSearcher.java (working copy) @@ -1,103 +0,0 @@ -package org.apache.lucene.facet.example.adaptive; - -import java.util.List; - -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.example.simple.SimpleUtils; -import org.apache.lucene.facet.search.AdaptiveFacetsAccumulator; -import org.apache.lucene.facet.search.ScoredDocIdCollector; -import org.apache.lucene.facet.search.params.CountFacetRequest; -import org.apache.lucene.facet.search.params.FacetSearchParams; -import org.apache.lucene.facet.search.results.FacetResult; -import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.MultiCollector; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.TopScoreDocCollector; -import org.apache.lucene.store.Directory; - -/* - * 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. - */ - -/** - * Search with facets through the {@link AdaptiveFacetsAccumulator} - * - * @lucene.experimental - */ -public class AdaptiveSearcher { - - /** - * Search with facets through the {@link AdaptiveFacetsAccumulator} - * @param indexDir Directory of the search index. - * @param taxoDir Directory of the taxonomy index. - * @throws Exception on error (no detailed exception handling here for sample simplicity - * @return facet results - */ - public static List searchWithFacets (Directory indexDir, Directory taxoDir) throws Exception { - // prepare index reader and taxonomy. - TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); - IndexReader indexReader = DirectoryReader.open(indexDir); - - // prepare searcher to search against - IndexSearcher searcher = new IndexSearcher(indexReader); - - // faceted search is working in 2 steps: - // 1. collect matching documents - // 2. aggregate facets for collected documents and - // generate the requested faceted results from the aggregated facets - - // step 1: collect matching documents into a collector - Query q = new TermQuery(new Term(SimpleUtils.TEXT,"white")); - ExampleUtils.log("Query: "+q); - - // regular collector for scoring matched documents - TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(10, true); - - // docids collector for guiding facets accumulation (scoring disabled) - ScoredDocIdCollector docIdsCollecor = ScoredDocIdCollector.create(indexReader.maxDoc(), false); - - // Faceted search parameters indicate which facets are we interested in - FacetSearchParams facetSearchParams = new FacetSearchParams( - new CountFacetRequest(new CategoryPath("root", "a"), 10)); - - // search, into both collectors. note: in case only facets accumulation - // is required, the topDocCollector part can be totally discarded - searcher.search(q, MultiCollector.wrap(topDocsCollector, docIdsCollecor)); - - // Obtain facets results and print them - AdaptiveFacetsAccumulator accumulator = new AdaptiveFacetsAccumulator(facetSearchParams, indexReader, taxo); - List res = accumulator.accumulate(docIdsCollecor.getScoredDocIDs()); - - int i = 0; - for (FacetResult facetResult : res) { - ExampleUtils.log("Res "+(i++)+": "+facetResult); - } - - // we're done, close the index reader and the taxonomy. - indexReader.close(); - taxo.close(); - - return res; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsIndexer.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsIndexer.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsIndexer.java (working copy) @@ -1,119 +0,0 @@ -package org.apache.lucene.facet.example.association; - -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.associations.AssociationsFacetFields; -import org.apache.lucene.facet.associations.CategoryAssociation; -import org.apache.lucene.facet.associations.CategoryAssociationsContainer; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.example.simple.SimpleUtils; -import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.IndexWriterConfig.OpenMode; -import org.apache.lucene.store.Directory; - -/* - * 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. - */ - -/** - * Sample indexer creates an index, and adds to it sample documents with - * categories, which can be simple or contain associations. - * - * @lucene.experimental - */ -public class CategoryAssociationsIndexer { - - /** - * Create an index, and adds to it sample documents and categories. - * - * @param indexDir - * Directory in which the index should be created. - * @param taxoDir - * Directory in which the taxonomy index should be created. - * @throws Exception - * on error (no detailed exception handling here for sample - * simplicity - */ - public static void index(Directory indexDir, Directory taxoDir) throws Exception { - - // create and open an index writer - IndexWriter iw = new IndexWriter(indexDir, new IndexWriterConfig(ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer)); - - // create and open a taxonomy writer - TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); - - AssociationsFacetFields assocFacetFields = new AssociationsFacetFields(taxo); - - // loop over sample documents - int nDocsAdded = 0; - int nFacetsAdded = 0; - for (int docNum = 0; docNum < SimpleUtils.docTexts.length; docNum++) { - ExampleUtils.log(" ++++ DOC ID: " + docNum); - // obtain the sample categories for current document - CategoryAssociationsContainer associations = new CategoryAssociationsContainer(); - for (CategoryPath path : SimpleUtils.categories[docNum]) { - associations.setAssociation(path, null); - ExampleUtils.log("\t ++++ PATH: " + path); - ++nFacetsAdded; - } - // and also those with associations - CategoryPath[] associationsPaths = CategoryAssociationsUtils.categories[docNum]; - CategoryAssociation[] associationsValues = CategoryAssociationsUtils.associations[docNum]; - for (int i = 0; i < associationsPaths.length; i++) { - associations.setAssociation(associationsPaths[i], associationsValues[i]); - ExampleUtils.log("\t $$$$ Association: (" + associationsPaths[i] + "," + associationsValues[i] + ")"); - ++nFacetsAdded; - } - - // create a plain Lucene document and add some regular Lucene fields - // to it - Document doc = new Document(); - doc.add(new TextField(SimpleUtils.TITLE, SimpleUtils.docTitles[docNum], Field.Store.YES)); - doc.add(new TextField(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum], Field.Store.NO)); - - // invoke the category document builder for adding categories to the - // document and, as required, to the taxonomy index - assocFacetFields.addFields(doc, associations); - - // finally add the document to the index - iw.addDocument(doc); - - nDocsAdded++; - } - - // commit changes. - // we commit changes to the taxonomy index prior to committing them to - // the search index. - // this is important, so that all facets referred to by documents in the - // search index - // will indeed exist in the taxonomy index. - taxo.commit(); - iw.commit(); - - // close the taxonomy index and the index - all modifications are - // now safely in the provided directories: indexDir and taxoDir. - taxo.close(); - iw.close(); - - ExampleUtils.log("Indexed " + nDocsAdded + " documents with overall " + nFacetsAdded + " facets."); - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsMain.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsMain.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsMain.java (working copy) @@ -1,82 +0,0 @@ -package org.apache.lucene.facet.example.association; - -import java.util.List; - -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.RAMDirectory; - -import org.apache.lucene.facet.example.ExampleResult; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.search.results.FacetResult; - -/* - * 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. - */ - -/** - * Driver for the simple sample. - * - * @lucene.experimental - */ -public class CategoryAssociationsMain { - - /** - * Driver for the simple sample. - * @throws Exception on error (no detailed exception handling here for sample simplicity - */ - public static void main(String[] args) throws Exception { - new CategoryAssociationsMain().runSumIntAssociationSample(); - new CategoryAssociationsMain().runSumFloatAssociationSample(); - ExampleUtils.log("DONE"); - } - - public ExampleResult runSumIntAssociationSample() throws Exception { - - // create Directories for the search index and for the taxonomy index - Directory indexDir = new RAMDirectory();//FSDirectory.open(new File("/tmp/111")); - Directory taxoDir = new RAMDirectory(); - - // index the sample documents - ExampleUtils.log("index the sample documents..."); - CategoryAssociationsIndexer.index(indexDir, taxoDir); - - ExampleUtils.log("search the sample documents..."); - List facetRes = CategoryAssociationsSearcher.searchSumIntAssociation(indexDir, taxoDir); - - ExampleResult res = new ExampleResult(); - res.setFacetResults(facetRes); - return res; - } - - public ExampleResult runSumFloatAssociationSample() throws Exception { - - // create Directories for the search index and for the taxonomy index - Directory indexDir = new RAMDirectory();//FSDirectory.open(new File("/tmp/111")); - Directory taxoDir = new RAMDirectory(); - - // index the sample documents - ExampleUtils.log("index the sample documents..."); - CategoryAssociationsIndexer.index(indexDir, taxoDir); - - ExampleUtils.log("search the sample documents..."); - List facetRes = CategoryAssociationsSearcher.searchSumFloatAssociation(indexDir, taxoDir); - - ExampleResult res = new ExampleResult(); - res.setFacetResults(facetRes); - return res; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsSearcher.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsSearcher.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsSearcher.java (working copy) @@ -1,75 +0,0 @@ -package org.apache.lucene.facet.example.association; - -import java.util.List; - -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.store.Directory; - -import org.apache.lucene.facet.example.simple.SimpleSearcher; -import org.apache.lucene.facet.search.params.associations.AssociationFloatSumFacetRequest; -import org.apache.lucene.facet.search.params.associations.AssociationIntSumFacetRequest; -import org.apache.lucene.facet.search.results.FacetResult; -import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; - -/* - * 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. - */ - -/** - * AssociationSearcher searches index with facets, evaluating the facets with - * their associated $int value - * - * @lucene.experimental - */ -public class CategoryAssociationsSearcher { - - /** Search an index with a sum of int-association. */ - public static List searchSumIntAssociation(Directory indexDir, Directory taxoDir) throws Exception { - // prepare index reader - IndexReader indexReader = DirectoryReader.open(indexDir); - TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); - - AssociationIntSumFacetRequest facetRequest = new AssociationIntSumFacetRequest(new CategoryPath("tags"), 10); - List res = SimpleSearcher.searchWithRequest(indexReader, taxo, null, facetRequest); - - // close readers - taxo.close(); - indexReader.close(); - - return res; - } - - /** Search an index with a sum of float-association. */ - public static List searchSumFloatAssociation(Directory indexDir, Directory taxoDir) throws Exception { - // prepare index reader - IndexReader indexReader = DirectoryReader.open(indexDir); - TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); - - AssociationFloatSumFacetRequest facetRequest = new AssociationFloatSumFacetRequest(new CategoryPath("genre"), 10); - - List res = SimpleSearcher.searchWithRequest(indexReader, taxo, null, facetRequest); - - // close readers - taxo.close(); - indexReader.close(); - - return res; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsUtils.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsUtils.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/association/CategoryAssociationsUtils.java (working copy) @@ -1,70 +0,0 @@ -package org.apache.lucene.facet.example.association; - -import org.apache.lucene.facet.associations.CategoryAssociation; -import org.apache.lucene.facet.associations.CategoryFloatAssociation; -import org.apache.lucene.facet.associations.CategoryIntAssociation; -import org.apache.lucene.facet.taxonomy.CategoryPath; - -/* - * 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. - */ - -/** - * @lucene.experimental - */ -public class CategoryAssociationsUtils { - - /** - * Categories: categories[D][N] == category-path with association no. N for - * document no. D. - */ - public static CategoryPath[][] categories = { - // Doc #1 - { new CategoryPath("tags", "lucene") , - new CategoryPath("genre", "computing") - }, - - // Doc #2 - { new CategoryPath("tags", "lucene"), - new CategoryPath("tags", "solr"), - new CategoryPath("genre", "computing"), - new CategoryPath("genre", "software") - } - }; - - public static CategoryAssociation[][] associations = { - // Doc #1 associations - { - /* 3 occurrences for tag 'lucene' */ - new CategoryIntAssociation(3), - /* 87% confidence level of genre 'computing' */ - new CategoryFloatAssociation(0.87f) - }, - - // Doc #2 associations - { - /* 1 occurrence for tag 'lucene' */ - new CategoryIntAssociation(1), - /* 2 occurrences for tag 'solr' */ - new CategoryIntAssociation(2), - /* 75% confidence level of genre 'computing' */ - new CategoryFloatAssociation(0.75f), - /* 34% confidence level of genre 'software' */ - new CategoryFloatAssociation(0.34f), - } - }; - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/merge/TaxonomyMergeUtils.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/merge/TaxonomyMergeUtils.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/merge/TaxonomyMergeUtils.java (working copy) @@ -1,105 +0,0 @@ -package org.apache.lucene.facet.example.merge; - -import java.io.IOException; -import java.util.List; - -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.index.OrdinalMappingAtomicReader; -import org.apache.lucene.facet.index.params.FacetIndexingParams; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.DiskOrdinalMap; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.MemoryOrdinalMap; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.OrdinalMap; -import org.apache.lucene.index.AtomicReader; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.MultiReader; -import org.apache.lucene.store.Directory; - -/* - * 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. - */ - -/** - * @lucene.experimental - */ -public class TaxonomyMergeUtils { - - /** - * Merges the given taxonomy and index directories. Note that this method - * opens {@link DirectoryTaxonomyWriter} and {@link IndexWriter} on the - * respective destination indexes. Therefore if you have a writer open on any - * of them, it should be closed, or you should use - * {@link #merge(Directory, Directory, IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams)} - * instead. - * - * @see #merge(Directory, Directory, IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams) - */ - public static void merge(Directory srcIndexDir, Directory srcTaxDir, Directory destIndexDir, Directory destTaxDir, - FacetIndexingParams params) throws IOException { - IndexWriter destIndexWriter = new IndexWriter(destIndexDir, - new IndexWriterConfig(ExampleUtils.EXAMPLE_VER, null)); - DirectoryTaxonomyWriter destTaxWriter = new DirectoryTaxonomyWriter(destTaxDir); - merge(srcIndexDir, srcTaxDir, new MemoryOrdinalMap(), destIndexWriter, destTaxWriter, params); - destTaxWriter.close(); - destIndexWriter.close(); - } - - /** - * Merges the given taxonomy and index directories and commits the changes to - * the given writers. This method uses {@link MemoryOrdinalMap} to store the - * mapped ordinals. If you cannot afford the memory, you can use - * {@link #merge(Directory, Directory, DirectoryTaxonomyWriter.OrdinalMap, IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams)} - * by passing {@link DiskOrdinalMap}. - * - * @see #merge(Directory, Directory, DirectoryTaxonomyWriter.OrdinalMap, - * IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams) - */ - public static void merge(Directory srcIndexDir, Directory srcTaxDir, IndexWriter destIndexWriter, - DirectoryTaxonomyWriter destTaxWriter, FacetIndexingParams params) throws IOException { - merge(srcIndexDir, srcTaxDir, new MemoryOrdinalMap(), destIndexWriter, destTaxWriter, params); - } - - /** - * Merges the given taxonomy and index directories and commits the changes to - * the given writers. - */ - public static void merge(Directory srcIndexDir, Directory srcTaxDir, OrdinalMap map, IndexWriter destIndexWriter, - DirectoryTaxonomyWriter destTaxWriter, FacetIndexingParams params) throws IOException { - // merge the taxonomies - destTaxWriter.addTaxonomy(srcTaxDir, map); - int ordinalMap[] = map.getMap(); - DirectoryReader reader = DirectoryReader.open(srcIndexDir, -1); - List leaves = reader.leaves(); - int numReaders = leaves.size(); - AtomicReader wrappedLeaves[] = new AtomicReader[numReaders]; - for (int i = 0; i < numReaders; i++) { - wrappedLeaves[i] = new OrdinalMappingAtomicReader(leaves.get(i).reader(), ordinalMap, params); - } - try { - destIndexWriter.addIndexes(new MultiReader(wrappedLeaves)); - - // commit changes to taxonomy and index respectively. - destTaxWriter.commit(); - destIndexWriter.commit(); - } finally { - reader.close(); - } - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java (working copy) @@ -1,202 +0,0 @@ -package org.apache.lucene.facet.example.multiCL; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.example.simple.SimpleUtils; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.index.params.CategoryListParams; -import org.apache.lucene.facet.index.params.FacetIndexingParams; -import org.apache.lucene.facet.index.params.PerDimensionIndexingParams; -import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.IndexWriterConfig.OpenMode; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.RAMDirectory; - -/* - * 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. - */ - -/** - * Sample indexer creates an index, and adds to it sample documents and facets - * with multiple CategoryLists specified for different facets, so there are different - * category lists for different facets. - * - * @lucene.experimental - */ -public class MultiCLIndexer { - - // Number of documents to index - public static int NUM_DOCS = 100; - // Number of facets to add per document - public static int NUM_FACETS_PER_DOC = 10; - // Number of tokens in title - public static int TITLE_LENGTH = 5; - // Number of tokens in text - public static int TEXT_LENGTH = 100; - - // Lorum ipsum to use as content - this will be tokenized and used for document - // titles/text. - static String words = "Sed ut perspiciatis unde omnis iste natus error sit " - + "voluptatem accusantium doloremque laudantium totam rem aperiam " - + "eaque ipsa quae ab illo inventore veritatis et quasi architecto " - + "beatae vitae dicta sunt explicabo Nemo enim ipsam voluptatem " - + "quia voluptas sit aspernatur aut odit aut fugit sed quia consequuntur " - + "magni dolores eos qui ratione voluptatem sequi nesciunt Neque porro " - + "quisquam est qui dolorem ipsum quia dolor sit amet consectetur adipisci velit " - + "sed quia non numquam eius modi tempora incidunt ut labore et dolore " - + "magnam aliquam quaerat voluptatem Ut enim ad minima veniam " - + "quis nostrum exercitationem ullam corporis suscipit laboriosam " - + "nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure" - + "reprehenderit qui in ea voluptate velit esse quam nihil molestiae " - + "consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur"; - // PerDimensionIndexingParams for multiple category lists - public static final PerDimensionIndexingParams MULTI_IPARAMS; - - // Initialize PerDimensionIndexingParams - static { - Map paramsMap = new HashMap(); - paramsMap.put(new CategoryPath("0"), new CategoryListParams("$Digits$Zero")); - paramsMap.put(new CategoryPath("1"), new CategoryListParams("$Digits$One")); - paramsMap.put(new CategoryPath("2"), new CategoryListParams("$Digits$Two")); - paramsMap.put(new CategoryPath("3"), new CategoryListParams("$Digits$Three")); - paramsMap.put(new CategoryPath("4"), new CategoryListParams("$Digits$Four")); - paramsMap.put(new CategoryPath("5"), new CategoryListParams("$Digits$Five")); - MULTI_IPARAMS = new PerDimensionIndexingParams(paramsMap); - } - - /** - * Create an index, and adds to it sample documents and facets. - * @param indexDir Directory in which the index should be created. - * @param taxoDir Directory in which the taxonomy index should be created. - * @throws Exception on error (no detailed exception handling here for sample simplicity - */ - public static void index(Directory indexDir, Directory taxoDir) - throws Exception { - - Random random = new Random(2003); - - String[] docTitles = new String[NUM_DOCS]; - String[] docTexts = new String[NUM_DOCS]; - CategoryPath[][] cPaths = new CategoryPath[NUM_DOCS][NUM_FACETS_PER_DOC]; - - String[] tokens = words.split(" "); - for (int docNum = 0; docNum < NUM_DOCS; docNum++) { - String title = ""; - String text = ""; - for (int j = 0; j < TITLE_LENGTH; j++) { - title = title + tokens[random.nextInt(tokens.length)] + " "; - } - docTitles[docNum] = title; - - for (int j = 0; j < TEXT_LENGTH; j++) { - text = text + tokens[random.nextInt(tokens.length)] + " "; - } - docTexts[docNum] = text; - - for (int facetNum = 0; facetNum < NUM_FACETS_PER_DOC; facetNum++) { - cPaths[docNum][facetNum] = new CategoryPath(Integer - .toString(random.nextInt(7)), Integer.toString(random.nextInt(10))); - } - } - index(indexDir, taxoDir, MULTI_IPARAMS, docTitles, docTexts, cPaths); - } - - /** - * More advanced method for specifying custom indexing params, doc texts, - * doc titles and category paths. - */ - public static void index(Directory indexDir, Directory taxoDir, - FacetIndexingParams iParams, String[] docTitles, - String[] docTexts, CategoryPath[][] cPaths) throws Exception { - // create and open an index writer - IndexWriter iw = new IndexWriter(indexDir, new IndexWriterConfig( - ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer).setOpenMode(OpenMode.CREATE)); - // create and open a taxonomy writer - DirectoryTaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); - index(iw, taxo, iParams, docTitles, docTexts, cPaths); - } - - /** - * More advanced method for specifying custom indexing params, doc texts, - * doc titles and category paths. - *

- * Create an index, and adds to it sample documents and facets. - * @throws Exception - * on error (no detailed exception handling here for sample - * simplicity - */ - public static void index(IndexWriter iw, DirectoryTaxonomyWriter taxo, - FacetIndexingParams iParams, String[] docTitles, - String[] docTexts, CategoryPath[][] cPaths) throws Exception { - - // loop over sample documents - int nDocsAdded = 0; - int nFacetsAdded = 0; - for (int docNum = 0; docNum < SimpleUtils.docTexts.length; docNum++) { - List facetList = Arrays.asList(cPaths[docNum]); - - // we do not alter indexing parameters! - // FacetFields adds the categories to the document in addFields() - FacetFields facetFields = new FacetFields(taxo, iParams); - - // create a plain Lucene document and add some regular Lucene fields - // to it - Document doc = new Document(); - doc.add(new TextField(SimpleUtils.TITLE, docTitles[docNum], Field.Store.YES)); - doc.add(new TextField(SimpleUtils.TEXT, docTexts[docNum], Field.Store.NO)); - - // finally add the document to the index - facetFields.addFields(doc, facetList); - iw.addDocument(doc); - - nDocsAdded++; - nFacetsAdded += facetList.size(); - } - - // commit changes. - // we commit changes to the taxonomy index prior to committing them to - // the search index. - // this is important, so that all facets referred to by documents in the - // search index - // will indeed exist in the taxonomy index. - taxo.commit(); - iw.commit(); - - // close the taxonomy index and the index - all modifications are - // now safely in the provided directories: indexDir and taxoDir. - taxo.close(); - iw.close(); - - ExampleUtils.log("Indexed " + nDocsAdded + " documents with overall " - + nFacetsAdded + " facets."); - } - - public static void main(String[] args) throws Exception { - index(new RAMDirectory(), new RAMDirectory()); - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLMain.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLMain.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLMain.java (working copy) @@ -1,65 +0,0 @@ -package org.apache.lucene.facet.example.multiCL; - -import java.util.List; - -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.RAMDirectory; - -import org.apache.lucene.facet.example.ExampleResult; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.search.results.FacetResult; - -/* - * 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. - */ - -/** - * @lucene.experimental - */ -public class MultiCLMain { - - /** - * Driver for the multi sample. - * - * @throws Exception - * on error (no detailed exception handling here for sample - * simplicity - */ - public static void main(String[] args) throws Exception { - new MultiCLMain().runSample(); - ExampleUtils.log("DONE"); - } - - public ExampleResult runSample() throws Exception { - - // create Directories for the search index and for the taxonomy index - Directory indexDir = new RAMDirectory(); - Directory taxoDir = new RAMDirectory(); - - // index the sample documents - ExampleUtils.log("index the sample documents..."); - MultiCLIndexer.index(indexDir, taxoDir); - - ExampleUtils.log("search the sample documents..."); - List facetRes = MultiCLSearcher.searchWithFacets(indexDir, - taxoDir, MultiCLIndexer.MULTI_IPARAMS); - - ExampleResult res = new ExampleResult(); - res.setFacetResults(facetRes); - return res; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLSearcher.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLSearcher.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLSearcher.java (working copy) @@ -1,127 +0,0 @@ -package org.apache.lucene.facet.example.multiCL; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.TopScoreDocCollector; -import org.apache.lucene.store.Directory; - -import org.apache.lucene.search.MultiCollector; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.example.simple.SimpleUtils; -import org.apache.lucene.facet.index.params.FacetIndexingParams; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.search.params.CountFacetRequest; -import org.apache.lucene.facet.search.params.FacetRequest; -import org.apache.lucene.facet.search.params.FacetSearchParams; -import org.apache.lucene.facet.search.results.FacetResult; -import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; - -/* - * 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. - */ - -/** - * MultiSearcher searches index with facets over an index with multiple - * category lists. - * - * @lucene.experimental - */ -public class MultiCLSearcher { - - /** - * Search an index with facets. - * - * @param indexDir - * Directory of the search index. - * @param taxoDir - * Directory of the taxonomy index. - * @throws Exception - * on error (no detailed exception handling here for sample - * simplicity - * @return facet results - */ - public static List searchWithFacets(Directory indexDir, - Directory taxoDir, FacetIndexingParams iParams) throws Exception { - - // prepare index reader and taxonomy. - IndexReader indexReader = DirectoryReader.open(indexDir); - TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); - - // Get results - List results = searchWithFacets(indexReader, taxo, iParams); - - // we're done, close the index reader and the taxonomy. - indexReader.close(); - taxo.close(); - return results; - } - - public static List searchWithFacets(IndexReader indexReader, - TaxonomyReader taxo, FacetIndexingParams iParams) throws Exception { - // prepare searcher to search against - IndexSearcher searcher = new IndexSearcher(indexReader); - - // faceted search is working in 2 steps: - // 1. collect matching documents - // 2. aggregate facets for collected documents and - // generate the requested faceted results from the aggregated facets - - // step 1: create a query for finding matching documents for which we - // accumulate facets - Query q = new TermQuery(new Term(SimpleUtils.TEXT, "Quis")); - ExampleUtils.log("Query: " + q); - - TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(10, true); - - // Faceted search parameters indicate which facets are we interested in - List facetRequests = new ArrayList(); - facetRequests.add(new CountFacetRequest(new CategoryPath("5"), 10)); - facetRequests.add(new CountFacetRequest(new CategoryPath("5", "5"), 10)); - facetRequests.add(new CountFacetRequest(new CategoryPath("6", "2"), 10)); - FacetSearchParams facetSearchParams = new FacetSearchParams(facetRequests, iParams); - - // Facets collector is the simplest interface for faceted search. - // It provides faceted search functions that are sufficient to many - // application, - // although it is insufficient for tight control on faceted search - // behavior - in those - // situations other, more low-level interfaces are available, as - // demonstrated in other search examples. - FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, indexReader, taxo); - - // perform documents search and facets accumulation - searcher.search(q, MultiCollector.wrap(topDocsCollector, facetsCollector)); - - // Obtain facets results and print them - List res = facetsCollector.getFacetResults(); - - int i = 0; - for (FacetResult facetResult : res) { - ExampleUtils.log("Res " + (i++) + ": " + facetResult); - } - return res; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleIndexer.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleIndexer.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleIndexer.java (working copy) @@ -1,98 +0,0 @@ -package org.apache.lucene.facet.example.simple; - -import java.util.Arrays; -import java.util.List; - -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.TextField; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.index.FacetFields; -import org.apache.lucene.facet.taxonomy.CategoryPath; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.IndexWriterConfig.OpenMode; -import org.apache.lucene.store.Directory; - -/* - * 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. - */ - -/** - * Sample indexer creates an index, and adds to it sample documents and facets. - * - * @lucene.experimental - */ -public class SimpleIndexer { - - /** - * Create an index, and adds to it sample documents and facets. - * @param indexDir Directory in which the index should be created. - * @param taxoDir Directory in which the taxonomy index should be created. - * @throws Exception on error (no detailed exception handling here for sample simplicity - */ - public static void index (Directory indexDir, Directory taxoDir) throws Exception { - - // create and open an index writer - final IndexWriter iw = new IndexWriter(indexDir, - new IndexWriterConfig(ExampleUtils.EXAMPLE_VER, SimpleUtils.analyzer)); - - // create and open a taxonomy writer - final TaxonomyWriter taxo = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); - - // FacetFields adds the categories to the document in addFields() - final FacetFields facetFields = new FacetFields(taxo); - - // loop over sample documents - int nDocsAdded = 0; - int nFacetsAdded = 0; - for (int docNum = 0; docNum < SimpleUtils.docTexts.length; docNum++) { - // obtain the sample facets for current document - List facetList = Arrays.asList(SimpleUtils.categories[docNum]); - - // create a plain Lucene document and add some regular Lucene fields to it - Document doc = new Document(); - doc.add(new TextField(SimpleUtils.TITLE, SimpleUtils.docTitles[docNum], Field.Store.YES)); - doc.add(new TextField(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum], Field.Store.NO)); - - // add the facet fields to the document - facetFields.addFields(doc, facetList); - - // finally add the document to the index - iw.addDocument(doc); - - nDocsAdded ++; - nFacetsAdded += facetList.size(); - } - - // commit changes. - // we commit changes to the taxonomy index prior to committing them to the search index. - // this is important, so that all facets referred to by documents in the search index - // will indeed exist in the taxonomy index. - taxo.commit(); - iw.commit(); - - // close the taxonomy index and the index - all modifications are - // now safely in the provided directories: indexDir and taxoDir. - taxo.close(); - iw.close(); - - ExampleUtils.log("Indexed "+nDocsAdded+" documents with overall "+nFacetsAdded+" facets."); - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleMain.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleMain.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleMain.java (working copy) @@ -1,100 +0,0 @@ -package org.apache.lucene.facet.example.simple; - -import java.util.List; - -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.RAMDirectory; - -import org.apache.lucene.facet.example.ExampleResult; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.search.results.FacetResult; -import org.apache.lucene.facet.taxonomy.TaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; - -/* - * 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. - */ - -/** - * Driver for the simple sample. - * - * @lucene.experimental - */ -public class SimpleMain { - - /** - * Driver for the simple sample. - * @throws Exception on error (no detailed exception handling here for sample simplicity - */ - public static void main(String[] args) throws Exception { - new SimpleMain().runSimple(); - new SimpleMain().runDrillDown().getFacetResults(); - ExampleUtils.log("DONE"); - } - - public ExampleResult runSimple() throws Exception { - // create Directories for the search index and for the taxonomy index - Directory indexDir = new RAMDirectory(); - Directory taxoDir = new RAMDirectory(); - - // index the sample documents - ExampleUtils.log("index the sample documents..."); - SimpleIndexer.index(indexDir, taxoDir); - - // open readers - TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); - IndexReader indexReader = DirectoryReader.open(indexDir); - - ExampleUtils.log("search the sample documents..."); - List facetRes = SimpleSearcher.searchWithFacets(indexReader, taxo); - - // close readers - taxo.close(); - indexReader.close(); - - ExampleResult res = new ExampleResult(); - res.setFacetResults(facetRes); - return res; - } - - public ExampleResult runDrillDown() throws Exception { - // create Directories for the search index and for the taxonomy index - Directory indexDir = new RAMDirectory(); - Directory taxoDir = new RAMDirectory(); - - // index the sample documents - ExampleUtils.log("index the sample documents..."); - SimpleIndexer.index(indexDir, taxoDir); - - // open readers - TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); - IndexReader indexReader = DirectoryReader.open(indexDir); - - ExampleUtils.log("search the sample documents..."); - List facetRes = SimpleSearcher.searchWithDrillDown(indexReader, taxo); - - // close readers - taxo.close(); - indexReader.close(); - - ExampleResult res = new ExampleResult(); - res.setFacetResults(facetRes); - return res; - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java (working copy) @@ -1,164 +0,0 @@ -package org.apache.lucene.facet.example.simple; - -import java.util.Iterator; -import java.util.List; - -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.index.params.FacetIndexingParams; -import org.apache.lucene.facet.search.DrillDown; -import org.apache.lucene.facet.search.FacetsCollector; -import org.apache.lucene.facet.search.params.CountFacetRequest; -import org.apache.lucene.facet.search.params.FacetRequest; -import org.apache.lucene.facet.search.params.FacetSearchParams; -import org.apache.lucene.facet.search.results.FacetResult; -import org.apache.lucene.facet.search.results.FacetResultNode; -import org.apache.lucene.facet.taxonomy.CategoryPath; -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; -import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.TopScoreDocCollector; - -/* - * 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. - */ - -/** - * SampleSearcer searches index with facets. - * - * @lucene.experimental - */ -public class SimpleSearcher { - - /** - * Search an index with facets. - * @param indexReader index reader. - * @param taxoReader taxonomy reader. - * @throws Exception on error (no detailed exception handling here for sample simplicity - * @return facet results - */ - public static List searchWithFacets (IndexReader indexReader, - TaxonomyReader taxoReader) throws Exception { - CountFacetRequest facetRequest = new CountFacetRequest(new CategoryPath("root","a"), 10); - return searchWithRequest(indexReader, taxoReader, null, facetRequest); - } - - /** - * Search an index with facets for given facet requests. - * @param indexReader index reader. - * @param taxoReader taxonomy reader. - * @param indexingParams the facet indexing params - * @param facetRequests facet requests of interest - * @throws Exception on error (no detailed exception handling here for sample simplicity - * @return facet results - */ - public static List searchWithRequest(IndexReader indexReader, - TaxonomyReader taxoReader, FacetIndexingParams indexingParams, - FacetRequest... facetRequests) throws Exception { - Query q = new TermQuery(new Term(SimpleUtils.TEXT, "white")); - return searchWithRequestAndQuery(q, indexReader, taxoReader, - indexingParams, facetRequests); - } - - /** - * Search an index with facets for given query and facet requests. - * @param q query of interest - * @param indexReader index reader. - * @param taxoReader taxonomy reader. - * @param indexingParams the facet indexing params - * @param facetRequests facet requests of interest - * @throws Exception on error (no detailed exception handling here for sample simplicity - * @return facet results - */ - public static List searchWithRequestAndQuery(Query q, - IndexReader indexReader, TaxonomyReader taxoReader, - FacetIndexingParams indexingParams, FacetRequest... facetRequests) - throws Exception { - - ExampleUtils.log("Query: " + q); - // prepare searcher to search against - IndexSearcher searcher = new IndexSearcher(indexReader); - - // collect matching documents into a collector - TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(10, true); - - if (indexingParams == null) { - indexingParams = FacetIndexingParams.ALL_PARENTS; - } - - // Faceted search parameters indicate which facets are we interested in - FacetSearchParams facetSearchParams = new FacetSearchParams(indexingParams, facetRequests); - - FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, indexReader, taxoReader); - - // perform documents search and facets accumulation - searcher.search(q, MultiCollector.wrap(topDocsCollector, facetsCollector)); - - // Obtain facets results and print them - List res = facetsCollector.getFacetResults(); - - int i = 0; - for (FacetResult facetResult : res) { - ExampleUtils.log("Res " + (i++) + ": " + facetResult); - } - - return res; - } - - /** - * Search an index with facets drill-down. - * @param indexReader index reader. - * @param taxoReader taxonomy reader. - * @throws Exception on error (no detailed exception handling here for sample simplicity - * @return facet results - */ - public static List searchWithDrillDown(IndexReader indexReader, - TaxonomyReader taxoReader) throws Exception { - - final FacetIndexingParams indexingParams = FacetIndexingParams.ALL_PARENTS; - - // base query the user is interested in - Query baseQuery = new TermQuery(new Term(SimpleUtils.TEXT, "white")); - - // facet of interest - CountFacetRequest facetRequest = new CountFacetRequest(new CategoryPath("root","a"), 10); - - // initial search - all docs matching the base query will contribute to the accumulation - List res1 = searchWithRequest(indexReader, taxoReader, indexingParams, facetRequest); - - // a single result (because there was a single request) - FacetResult fres = res1.get(0); - - // assume the user is interested in the second sub-result - // (just take the second sub-result returned by the iterator - we know there are 3 results!) - Iterator resIterator = fres.getFacetResultNode().subResults.iterator(); - resIterator.next(); // skip first result - 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, 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 - // category of interest will contribute to the new accumulation - return searchWithRequestAndQuery(q2, indexReader, taxoReader, indexingParams, facetRequest); - } - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleUtils.java =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleUtils.java (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleUtils.java (working copy) @@ -1,71 +0,0 @@ -package org.apache.lucene.facet.example.simple; - -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.core.WhitespaceAnalyzer; -import org.apache.lucene.facet.example.ExampleUtils; -import org.apache.lucene.facet.taxonomy.CategoryPath; - -/* - * 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. - */ - -/** - * Some definitions for the Simple Sample. - * - * @lucene.experimental - */ -public class SimpleUtils { - - /** - * Documents text field. - */ - public static final String TEXT = "text"; - - /** - * Documents title field. - */ - public static final String TITLE = "title"; - - /** - * sample documents text (for the text field). - */ - public static String[] docTexts = { - "the white car is the one I want.", - "the white dog does not belong to anyone.", - }; - - /** - * sample documents titles (for the title field). - */ - public static String[] docTitles = { - "white car", - "white dog", - }; - - /** - * Categories: categories[D][N] == category-path no. N for document no. D. - */ - public static CategoryPath[][] categories = { - { new CategoryPath("root","a","f1"), new CategoryPath("root","a","f2") }, - { new CategoryPath("root","a","f1"), new CategoryPath("root","a","f3") }, - }; - - /** - * Analyzer used in the simple sample. - */ - public static final Analyzer analyzer = new WhitespaceAnalyzer(ExampleUtils.EXAMPLE_VER); - -} Index: lucene/facet/src/examples/org/apache/lucene/facet/example/simple/package.html =================================================================== --- lucene/facet/src/examples/org/apache/lucene/facet/example/simple/package.html (revision 1440418) +++ lucene/facet/src/examples/org/apache/lucene/facet/example/simple/package.html (working copy) @@ -1,17 +0,0 @@ - - - Simple faceted indexing and search sample - - -

Simple faceted indexing and search sample

- - A simple faceted example, showing how to: -
    -
  1. Create an index.
  2. -
  3. Add documents with facets to the index.
  4. -
  5. Search the index.
  6. -
- - For more complex examples see the other sample code packages. - - \ No newline at end of file Index: lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java (revision 0) +++ lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java (working copy) @@ -0,0 +1,104 @@ +package org.apache.lucene.facet.util; + +import java.io.IOException; +import java.util.List; + +import org.apache.lucene.facet.index.OrdinalMappingAtomicReader; +import org.apache.lucene.facet.index.params.FacetIndexingParams; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.DiskOrdinalMap; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.MemoryOrdinalMap; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.OrdinalMap; +import org.apache.lucene.index.AtomicReader; +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.MultiReader; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.Version; + +/* + * 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. + */ + +/** + * @lucene.experimental + */ +public class TaxonomyMergeUtils { + + /** + * Merges the given taxonomy and index directories. Note that this method + * opens {@link DirectoryTaxonomyWriter} and {@link IndexWriter} on the + * respective destination indexes. Therefore if you have a writer open on any + * of them, it should be closed, or you should use + * {@link #merge(Directory, Directory, IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams)} + * instead. + * + * @see #merge(Directory, Directory, IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams) + */ + public static void merge(Directory srcIndexDir, Directory srcTaxDir, Directory destIndexDir, Directory destTaxDir, + FacetIndexingParams params) throws IOException { + IndexWriter destIndexWriter = new IndexWriter(destIndexDir, new IndexWriterConfig(Version.LUCENE_42, null)); + DirectoryTaxonomyWriter destTaxWriter = new DirectoryTaxonomyWriter(destTaxDir); + merge(srcIndexDir, srcTaxDir, new MemoryOrdinalMap(), destIndexWriter, destTaxWriter, params); + destTaxWriter.close(); + destIndexWriter.close(); + } + + /** + * Merges the given taxonomy and index directories and commits the changes to + * the given writers. This method uses {@link MemoryOrdinalMap} to store the + * mapped ordinals. If you cannot afford the memory, you can use + * {@link #merge(Directory, Directory, DirectoryTaxonomyWriter.OrdinalMap, IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams)} + * by passing {@link DiskOrdinalMap}. + * + * @see #merge(Directory, Directory, DirectoryTaxonomyWriter.OrdinalMap, + * IndexWriter, DirectoryTaxonomyWriter, FacetIndexingParams) + */ + public static void merge(Directory srcIndexDir, Directory srcTaxDir, IndexWriter destIndexWriter, + DirectoryTaxonomyWriter destTaxWriter, FacetIndexingParams params) throws IOException { + merge(srcIndexDir, srcTaxDir, new MemoryOrdinalMap(), destIndexWriter, destTaxWriter, params); + } + + /** + * Merges the given taxonomy and index directories and commits the changes to + * the given writers. + */ + public static void merge(Directory srcIndexDir, Directory srcTaxDir, OrdinalMap map, IndexWriter destIndexWriter, + DirectoryTaxonomyWriter destTaxWriter, FacetIndexingParams params) throws IOException { + // merge the taxonomies + destTaxWriter.addTaxonomy(srcTaxDir, map); + int ordinalMap[] = map.getMap(); + DirectoryReader reader = DirectoryReader.open(srcIndexDir, -1); + List leaves = reader.leaves(); + int numReaders = leaves.size(); + AtomicReader wrappedLeaves[] = new AtomicReader[numReaders]; + for (int i = 0; i < numReaders; i++) { + wrappedLeaves[i] = new OrdinalMappingAtomicReader(leaves.get(i).reader(), ordinalMap, params); + } + try { + destIndexWriter.addIndexes(new MultiReader(wrappedLeaves)); + + // commit changes to taxonomy and index respectively. + destTaxWriter.commit(); + destIndexWriter.commit(); + } finally { + reader.close(); + } + } + +} Property changes on: lucene/facet/src/java/org/apache/lucene/facet/util/TaxonomyMergeUtils.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java (working copy) @@ -1,19 +1,7 @@ package org.apache.lucene.facet; -import java.io.IOException; - -import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.facet.search.results.FacetResult; import org.apache.lucene.facet.search.results.FacetResultNode; -import org.apache.lucene.facet.taxonomy.TaxonomyWriter; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; -import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.LuceneTestCase; /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -34,68 +22,6 @@ public class FacetTestUtils { - public static class IndexTaxonomyReaderPair { - public DirectoryReader indexReader; - public DirectoryTaxonomyReader taxReader; - public IndexSearcher indexSearcher; - - public void close() throws IOException { - indexReader.close(); - taxReader.close(); - } - - } - - public static class IndexTaxonomyWriterPair { - public IndexWriter indexWriter; - public TaxonomyWriter taxWriter; - - public void close() throws IOException { - indexWriter.close(); - taxWriter.close(); - } - - public void commit() throws IOException { - indexWriter.commit(); - taxWriter.commit(); - } - } - - public static Directory[][] createIndexTaxonomyDirs(int number) { - Directory[][] dirs = new Directory[number][2]; - for (int i = 0; i < number; i++) { - dirs[i][0] = LuceneTestCase.newDirectory(); - dirs[i][1] = LuceneTestCase.newDirectory(); - } - return dirs; - } - - public static IndexTaxonomyReaderPair[] createIndexTaxonomyReaderPair(Directory[][] dirs) throws IOException { - IndexTaxonomyReaderPair[] pairs = new IndexTaxonomyReaderPair[dirs.length]; - for (int i = 0; i < dirs.length; i++) { - IndexTaxonomyReaderPair pair = new IndexTaxonomyReaderPair(); - pair.indexReader = DirectoryReader.open(dirs[i][0]); - pair.indexSearcher = new IndexSearcher(pair.indexReader); - pair.taxReader = new DirectoryTaxonomyReader(dirs[i][1]); - pairs[i] = pair; - } - return pairs; - } - - public static IndexTaxonomyWriterPair[] createIndexTaxonomyWriterPair(Directory[][] dirs) throws IOException { - IndexTaxonomyWriterPair[] pairs = new IndexTaxonomyWriterPair[dirs.length]; - for (int i = 0; i < dirs.length; i++) { - IndexTaxonomyWriterPair pair = new IndexTaxonomyWriterPair(); - pair.indexWriter = new IndexWriter(dirs[i][0], new IndexWriterConfig( - LuceneTestCase.TEST_VERSION_CURRENT, new MockAnalyzer(LuceneTestCase.random()))); - pair.taxWriter = new DirectoryTaxonomyWriter(dirs[i][1]); - pair.indexWriter.commit(); - pair.taxWriter.commit(); - pairs[i] = pair; - } - return pairs; - } - public static String toSimpleString(FacetResult fr) { StringBuilder sb = new StringBuilder(); toSimpleString(0, sb, fr.getFacetResultNode(), ""); Index: lucene/facet/src/test/org/apache/lucene/facet/example/TestAdaptiveExample.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/example/TestAdaptiveExample.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/example/TestAdaptiveExample.java (working copy) @@ -1,40 +0,0 @@ -package org.apache.lucene.facet.example; - -import org.junit.Test; - -import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.facet.example.ExampleResult; -import org.apache.lucene.facet.example.adaptive.AdaptiveMain; - -/* - * 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. - */ - -/** - * Test that the adaptive example works as expected. This test helps to verify - * that examples code is alive! - */ -public class TestAdaptiveExample extends LuceneTestCase { - - @Test - public void testAdaptive () throws Exception { - ExampleResult res = new AdaptiveMain().runSample(); - assertNotNull("Null result!", res); - assertNotNull("Null facet result!", res.getFacetResults()); - assertEquals("Wrong number of results!",1, res.getFacetResults().size()); - assertEquals("Wrong number of facets!",3, res.getFacetResults().get(0).getNumValidDescendants()); - } -} Index: lucene/facet/src/test/org/apache/lucene/facet/example/TestAssociationExample.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/example/TestAssociationExample.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/example/TestAssociationExample.java (working copy) @@ -1,55 +0,0 @@ -package org.apache.lucene.facet.example; - -import org.junit.Test; - -import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.facet.example.ExampleResult; -import org.apache.lucene.facet.example.association.CategoryAssociationsMain; -import org.apache.lucene.facet.search.results.FacetResultNode; - -/* - * 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. - */ - -/** - * Test that the association example works as expected. This test helps to - * verify that examples code is alive! - */ -public class TestAssociationExample extends LuceneTestCase { - - private static final double[] EXPECTED_INT_SUM_RESULTS = { 4, 2}; - private static final double[] EXPECTED_FLOAT_SUM_RESULTS = { 1.62, 0.34}; - - @Test - public void testAssociationExamples() throws Exception { - assertExampleResult(new CategoryAssociationsMain().runSumIntAssociationSample(), EXPECTED_INT_SUM_RESULTS); - assertExampleResult(new CategoryAssociationsMain().runSumFloatAssociationSample(), EXPECTED_FLOAT_SUM_RESULTS); - } - - private void assertExampleResult(ExampleResult res, double[] expectedResults) { - assertNotNull("Null result!", res); - assertNotNull("Null facet result!", res.getFacetResults()); - assertEquals("Wrong number of results!", 1, res.getFacetResults().size()); - assertEquals("Wrong number of facets!", 2, res.getFacetResults().get(0).getNumValidDescendants()); - - Iterable it = res.getFacetResults().get(0).getFacetResultNode().subResults; - int i = 0; - for (FacetResultNode fResNode : it) { - assertEquals("Wrong result for facet "+fResNode.label, expectedResults[i++], fResNode.value, 1E-5); - } - } - -} Index: lucene/facet/src/test/org/apache/lucene/facet/example/TestMultiCLExample.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/example/TestMultiCLExample.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/example/TestMultiCLExample.java (working copy) @@ -1,77 +0,0 @@ -package org.apache.lucene.facet.example; - -import java.util.Iterator; -import java.util.List; - -import org.junit.Test; - -import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.facet.example.multiCL.MultiCLMain; -import org.apache.lucene.facet.search.results.FacetResult; -import org.apache.lucene.facet.search.results.FacetResultNode; - -/* - * 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. - */ - -/** - * Test that the multi-category list example works as expected. This test helps - * to verify that examples code is alive! - */ -public class TestMultiCLExample extends LuceneTestCase { - - @Test - public void testMulti() throws Exception { - ExampleResult res = new MultiCLMain().runSample(); - assertCorrectMultiResults(res); - } - - public static void assertCorrectMultiResults(ExampleResult exampleResults) { - List results = exampleResults.getFacetResults(); - FacetResult result = results.get(0); - assertNotNull("Result should not be null", result); - FacetResultNode node = result.getFacetResultNode(); - assertEquals("Invalid label", "5", node.label.toString()); - assertEquals("Invalid # of subresults", 3, node.subResults.size()); - - Iterator subResults = node.subResults.iterator(); - FacetResultNode sub = subResults.next(); - assertEquals("Invalid subresult value", 1.0, sub.value, 0.0); - assertEquals("Invalid subresult label", "5/2", sub.label.toString()); - sub = subResults.next(); - assertEquals("Invalid subresult value", 1.0, sub.value, 0.0); - assertEquals("Invalid subresult label", "5/7", sub.label.toString()); - sub = subResults.next(); - assertEquals("Invalid subresult value", 1.0, sub.value, 0.0); - assertEquals("Invalid subresult label", "5/5", sub.label.toString()); - - result = results.get(1); - node = result.getFacetResultNode(); - assertNotNull("Result should not be null", result); - assertEquals("Invalid label", "5/5", node.label.toString()); - assertEquals("Invalid value", 1, node.value, 0.0); - assertEquals("Invalid number of subresults", 0, node.subResults.size()); - - result = results.get(2); - node = result.getFacetResultNode(); - assertNotNull("Result should not be null", result); - assertEquals("Invalid label", "6/2", node.label.toString()); - assertEquals("Invalid value", 1, node.value, 0.0); - assertEquals("Invalid number of subresults", 0, node.subResults.size()); - - } - -} Index: lucene/facet/src/test/org/apache/lucene/facet/example/TestSimpleExample.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/example/TestSimpleExample.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/example/TestSimpleExample.java (working copy) @@ -1,67 +0,0 @@ -package org.apache.lucene.facet.example; - -import java.util.Iterator; - -import org.junit.Test; - -import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.facet.example.ExampleResult; -import org.apache.lucene.facet.example.simple.SimpleMain; -import org.apache.lucene.facet.search.results.FacetResult; -import org.apache.lucene.facet.search.results.FacetResultNode; - -/* - * 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. - */ - -/** - * Test that the simple example works as expected. This test helps to verify - * that examples code is alive! - */ -public class TestSimpleExample extends LuceneTestCase { - - @Test - public void testSimple() throws Exception { - ExampleResult res = new SimpleMain().runSimple(); - assertNotNull("Null result!", res); - assertNotNull("Null facet result!", res.getFacetResults()); - assertEquals("Wrong number of results!",1, res.getFacetResults().size()); - assertEquals("Wrong number of facets!",3, res.getFacetResults().get(0).getNumValidDescendants()); - } - - /** - * In drill down test we are drilling down to a facet that appears in a single document. - * As result, facets that without drill down got count of 2 will now get a count of 1. - */ - @Test - public void testDrillDown() throws Exception { - ExampleResult res = new SimpleMain().runDrillDown(); - assertNotNull("Null result!", res); - assertNotNull("Null facet result!", res.getFacetResults()); - assertEquals("Wrong number of results!",1, res.getFacetResults().size()); - - // drill down facet appears in only 1 doc, and that doc has only 2 facets - FacetResult facetResult = res.getFacetResults().get(0); - assertEquals("Wrong number of facets!",2, facetResult.getNumValidDescendants()); - - Iterator resIterator = facetResult.getFacetResultNode().subResults.iterator(); - assertTrue("Too few results", resIterator.hasNext()); - assertEquals("wrong count for first result out of 2", 1, (int)resIterator.next().value); - assertTrue("Too few results", resIterator.hasNext()); - assertEquals("wrong count for second result out of 2", 1, (int)resIterator.next().value); - assertFalse("Too many results!", resIterator.hasNext()); - } -} Index: lucene/facet/src/test/org/apache/lucene/facet/index/OrdinalMappingReaderTest.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/index/OrdinalMappingReaderTest.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/index/OrdinalMappingReaderTest.java (working copy) @@ -8,7 +8,6 @@ import org.apache.lucene.analysis.MockTokenizer; import org.apache.lucene.document.Document; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.example.merge.TaxonomyMergeUtils; import org.apache.lucene.facet.index.params.FacetIndexingParams; import org.apache.lucene.facet.search.FacetsCollector; import org.apache.lucene.facet.search.params.CountFacetRequest; @@ -18,6 +17,7 @@ import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; +import org.apache.lucene.facet.util.TaxonomyMergeUtils; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.RandomIndexWriter; Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (working copy) @@ -14,7 +14,6 @@ import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.FacetTestUtils; import org.apache.lucene.facet.index.FacetFields; import org.apache.lucene.facet.index.params.CategoryListParams; import org.apache.lucene.facet.index.params.FacetIndexingParams; @@ -77,12 +76,14 @@ @Test public void testDefault() throws Exception { - Directory[][] dirs = getDirs(); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); + // create and open an index writer - RandomIndexWriter iw = new RandomIndexWriter(random(), dirs[0][0], newIndexWriterConfig( + RandomIndexWriter iw = new RandomIndexWriter(random(), indexDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); PerDimensionIndexingParams iParams = new PerDimensionIndexingParams(Collections.emptyMap()); @@ -92,7 +93,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -105,17 +106,19 @@ assertOrdinalsExist("$facets", ir); IOUtils.close(tr, ir, iw, tw); - IOUtils.close(dirs[0]); + IOUtils.close(indexDir, taxoDir); } @Test public void testCustom() throws Exception { - Directory[][] dirs = getDirs(); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); + // create and open an index writer - RandomIndexWriter iw = new RandomIndexWriter(random(), dirs[0][0], newIndexWriterConfig( + RandomIndexWriter iw = new RandomIndexWriter(random(), indexDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); PerDimensionIndexingParams iParams = new PerDimensionIndexingParams( Collections.singletonMap(new CategoryPath("Author"), new CategoryListParams("$author"))); @@ -125,7 +128,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -139,17 +142,19 @@ assertOrdinalsExist("$author", ir); IOUtils.close(tr, ir, iw, tw); - IOUtils.close(dirs[0]); + IOUtils.close(indexDir, taxoDir); } @Test public void testTwoCustomsSameField() throws Exception { - Directory[][] dirs = getDirs(); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); + // create and open an index writer - RandomIndexWriter iw = new RandomIndexWriter(random(), dirs[0][0], newIndexWriterConfig( + RandomIndexWriter iw = new RandomIndexWriter(random(), indexDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); Map paramsMap = new HashMap(); paramsMap.put(new CategoryPath("Band"), new CategoryListParams("$music")); @@ -161,7 +166,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -176,7 +181,7 @@ assertOrdinalsExist("$music", ir); IOUtils.close(tr, ir, iw, tw); - IOUtils.close(dirs[0]); + IOUtils.close(indexDir, taxoDir); } private void assertOrdinalsExist(String field, IndexReader ir) throws IOException { @@ -191,12 +196,14 @@ @Test public void testDifferentFieldsAndText() throws Exception { - Directory[][] dirs = getDirs(); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); + // create and open an index writer - RandomIndexWriter iw = new RandomIndexWriter(random(), dirs[0][0], newIndexWriterConfig( + RandomIndexWriter iw = new RandomIndexWriter(random(), indexDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); Map paramsMap = new HashMap(); paramsMap.put(new CategoryPath("Band"), new CategoryListParams("$bands")); @@ -208,7 +215,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -222,17 +229,19 @@ assertOrdinalsExist("$composers", ir); IOUtils.close(tr, ir, iw, tw); - IOUtils.close(dirs[0]); + IOUtils.close(indexDir, taxoDir); } @Test public void testSomeSameSomeDifferent() throws Exception { - Directory[][] dirs = getDirs(); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); + // create and open an index writer - RandomIndexWriter iw = new RandomIndexWriter(random(), dirs[0][0], newIndexWriterConfig( + RandomIndexWriter iw = new RandomIndexWriter(random(), indexDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false))); // create and open a taxonomy writer - TaxonomyWriter tw = new DirectoryTaxonomyWriter(dirs[0][1], OpenMode.CREATE); + TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE); Map paramsMap = new HashMap(); paramsMap.put(new CategoryPath("Band"), new CategoryListParams("$music")); @@ -246,7 +255,7 @@ tw.commit(); // prepare index reader and taxonomy. - TaxonomyReader tr = new DirectoryTaxonomyReader(dirs[0][1]); + TaxonomyReader tr = new DirectoryTaxonomyReader(taxoDir); // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); @@ -259,13 +268,9 @@ assertOrdinalsExist("$literature", ir); IOUtils.close(tr, ir, iw, tw); - IOUtils.close(dirs[0]); + IOUtils.close(indexDir, taxoDir); } - private Directory[][] getDirs() { - return FacetTestUtils.createIndexTaxonomyDirs(1); - } - private void assertCorrectResults(FacetsCollector facetsCollector) throws IOException { List res = facetsCollector.getFacetResults(); Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestTotalFacetCounts.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/TestTotalFacetCounts.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/search/TestTotalFacetCounts.java (working copy) @@ -3,14 +3,20 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; +import java.util.Collections; +import org.apache.lucene.document.Document; import org.apache.lucene.facet.FacetTestCase; -import org.apache.lucene.facet.FacetTestUtils; -import org.apache.lucene.facet.FacetTestUtils.IndexTaxonomyReaderPair; -import org.apache.lucene.facet.FacetTestUtils.IndexTaxonomyWriterPair; +import org.apache.lucene.facet.index.FacetFields; import org.apache.lucene.facet.index.params.CategoryListParams; import org.apache.lucene.facet.index.params.FacetIndexingParams; import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyReader; +import org.apache.lucene.facet.taxonomy.TaxonomyWriter; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexWriter; import org.apache.lucene.store.Directory; import org.apache.lucene.util.IOUtils; import org.apache.lucene.util._TestUtil; @@ -35,9 +41,9 @@ public class TestTotalFacetCounts extends FacetTestCase { - private static void initCache(int numEntries) { + private static void initCache() { TotalFacetCountsCache.getSingleton().clear(); - TotalFacetCountsCache.getSingleton().setCacheSize(numEntries); // Set to keep one in mem + TotalFacetCountsCache.getSingleton().setCacheSize(1); // Set to keep one in mem } @Test @@ -50,12 +56,13 @@ } private void doTestWriteRead(final int partitionSize) throws IOException { - initCache(1); + initCache(); - // Create temporary RAMDirectories - Directory[][] dirs = FacetTestUtils.createIndexTaxonomyDirs(1); - // Create our index/taxonomy writers - IndexTaxonomyWriterPair[] writers = FacetTestUtils.createIndexTaxonomyWriterPair(dirs); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); + IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); + FacetIndexingParams iParams = new FacetIndexingParams() { @Override public int getPartitionSize() { @@ -75,36 +82,34 @@ // The counts that the TotalFacetCountsArray should have after adding // the below facets to the index. int[] expectedCounts = new int[] { 0, 3, 1, 3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1 }; - - // Add a facet to the index - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "a", "b"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "c", "d"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "a", "e"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "a", "d"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "c", "g"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "c", "z"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "b", "a"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "1", "2"); - TestTotalFacetCountsCache.addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "b", "c"); + String[] categories = new String[] { "a/b", "c/d", "a/e", "a/d", "c/g", "c/z", "b/a", "1/2", "b/c" }; + FacetFields facetFields = new FacetFields(taxoWriter, iParams); + for (String cat : categories) { + Document doc = new Document(); + facetFields.addFields(doc, Collections.singletonList(new CategoryPath(cat, '/'))); + indexWriter.addDocument(doc); + } + // Commit Changes - writers[0].close(); + IOUtils.close(indexWriter, taxoWriter); - IndexTaxonomyReaderPair[] readers = FacetTestUtils.createIndexTaxonomyReaderPair(dirs); + DirectoryReader indexReader = DirectoryReader.open(indexDir); + TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); int[] intArray = new int[iParams.getPartitionSize()]; TotalFacetCountsCache tfcc = TotalFacetCountsCache.getSingleton(); File tmpFile = _TestUtil.createTempFile("test", "tmp", TEMP_DIR); - tfcc.store(tmpFile, readers[0].indexReader, readers[0].taxReader, iParams); + tfcc.store(tmpFile, indexReader, taxoReader, iParams); tfcc.clear(); // not really required because TFCC overrides on load(), but in the test we need not rely on this. - tfcc.load(tmpFile, readers[0].indexReader, readers[0].taxReader, iParams); + tfcc.load(tmpFile, indexReader, taxoReader, iParams); // now retrieve the one just loaded - TotalFacetCounts totalCounts = tfcc.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + TotalFacetCounts totalCounts = tfcc.getTotalCounts(indexReader, taxoReader, iParams); int partition = 0; - for (int i=0; i getResults() { + return results; } @Override public void run() { try { - results = MultiCLSearcher.searchWithFacets(indexReader, taxoReader, iParams); + FacetSearchParams fsp = new FacetSearchParams(iParams, new CountFacetRequest(new CategoryPath("a"), 10), + new CountFacetRequest(new CategoryPath("b"), 10)); + IndexSearcher searcher = new IndexSearcher(indexReader); + FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader); + searcher.search(new MatchAllDocsQuery(), fc); + results = fc.getFacetResults(); } catch (Exception e) { throw new RuntimeException(e); } } } - // Instantiate threads, but do not start them Multi[] multis = new Multi[numThreads]; - for (int i = 0; i < numThreads - 1; i++) { - multis[i] = new Multi(slowIndexReader, slowTaxoReader, MultiCLIndexer.MULTI_IPARAMS); + for (int i = 0; i < numThreads; i++) { + multis[i] = new Multi(slowIndexReader, slowTaxoReader, FacetIndexingParams.ALL_PARENTS); } - // The last thread uses ONLY the DefaultFacetIndexingParams so that - // it references a different TFC cache. This will still result - // in valid results, but will only search one of the category lists - // instead of all of them. - multis[numThreads - 1] = new Multi(slowIndexReader, slowTaxoReader, FacetIndexingParams.ALL_PARENTS); - // Gentleman, start your engines for (Multi m : multis) { m.start(); } // Wait for threads and get results - ExampleResult[] multiResults = new ExampleResult[numThreads]; - for (int i = 0; i < numThreads; i++) { - multis[i].join(); - multiResults[i] = multis[i].getResults(); + String[] expLabelsA = new String[] { "a/d", "a/e", "a/b" }; + String[] expLabelsB = new String[] { "b/c", "b/a" }; + for (Multi m : multis) { + m.join(); + List facetResults = m.getResults(); + assertEquals("expected two results", 2, facetResults.size()); + + FacetResultNode nodeA = facetResults.get(0).getFacetResultNode(); + int i = 0; + for (FacetResultNode node : nodeA.subResults) { + assertEquals("wrong count", 1, (int) node.value); + assertEquals(expLabelsA[i++], node.label.toString('/')); + } + + FacetResultNode nodeB = facetResults.get(1).getFacetResultNode(); + i = 0; + for (FacetResultNode node : nodeB.subResults) { + assertEquals("wrong count", 1, (int) node.value); + assertEquals(expLabelsB[i++], node.label.toString('/')); + } } - - // Each of the (numThreads-1) should have the same predictable - // results, which we test for here. - for (int i = 0; i < numThreads - 1; i++) { - ExampleResult eResults = multiResults[i]; - TestMultiCLExample.assertCorrectMultiResults(eResults); - } - - // The last thread, which only searched over the - // DefaultFacetIndexingParams, - // has its own results - ExampleResult eResults = multiResults[numThreads - 1]; - List results = eResults.getFacetResults(); - assertEquals(3, results.size()); - String[] expLabels = new String[] { "5", "5/5", "6/2" }; - double[] expValues = new double[] { 0.0, 0.0, 1.0 }; - for (int i = 0; i < 3; i++) { - FacetResult result = results.get(i); - assertNotNull("Result should not be null", result); - FacetResultNode resNode = result.getFacetResultNode(); - assertEquals("Invalid label", expLabels[i], resNode.label.toString()); - assertEquals("Invalid value", expValues[i], resNode.value, 0.0); - assertEquals("Invalid number of subresults", 0, resNode.subResults.size()); - } - // we're done, close the index reader and the taxonomy. - slowIndexReader.close(); - slowTaxoReader.close(); - indexDir.close(); - taxoDir.close(); + + IOUtils.close(slowIndexReader, slowTaxoReader, indexDir, taxoDir); } /** @@ -245,77 +225,78 @@ @Test public void testGenerationalConsistency() throws Exception { // Create temporary RAMDirectories - Directory[][] dirs = FacetTestUtils.createIndexTaxonomyDirs(1); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); // Create our index/taxonomy writers - IndexTaxonomyWriterPair[] writers = FacetTestUtils.createIndexTaxonomyWriterPair(dirs); + IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); FacetIndexingParams iParams = FacetIndexingParams.ALL_PARENTS; // Add a facet to the index - addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "a", "b"); + addFacets(iParams, indexWriter, taxoWriter, "a", "b"); // Commit Changes - writers[0].indexWriter.commit(); - writers[0].taxWriter.commit(); + indexWriter.commit(); + taxoWriter.commit(); // Open readers - IndexTaxonomyReaderPair[] readers = FacetTestUtils.createIndexTaxonomyReaderPair(dirs); + DirectoryReader indexReader = DirectoryReader.open(indexDir); + TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); // As this is the first time we have invoked the TotalFacetCountsManager, // we should expect to compute and not read from disk. - TotalFacetCounts totalCounts = - TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + TotalFacetCounts totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); int prevGen = assertRecomputed(totalCounts, 0, "after first attempt to get it!"); // Repeating same operation should pull from the cache - not recomputed. assertTrue("Should be obtained from cache at 2nd attempt",totalCounts == - TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams)); + TFC.getTotalCounts(indexReader, taxoReader, iParams)); // Repeat the same operation as above. but clear first - now should recompute again initCache(); - totalCounts = TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); prevGen = assertRecomputed(totalCounts, prevGen, "after cache clear, 3rd attempt to get it!"); //store to file File outputFile = _TestUtil.createTempFile("test", "tmp", TEMP_DIR); initCache(); - TFC.store(outputFile, readers[0].indexReader, readers[0].taxReader, iParams); - totalCounts = TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + TFC.store(outputFile, indexReader, taxoReader, iParams); + totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); prevGen = assertRecomputed(totalCounts, prevGen, "after cache clear, 4th attempt to get it!"); //clear and load initCache(); - TFC.load(outputFile, readers[0].indexReader, readers[0].taxReader, iParams); - totalCounts = TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + TFC.load(outputFile, indexReader, taxoReader, iParams); + totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); prevGen = assertReadFromDisc(totalCounts, prevGen, "after 5th attempt to get it!"); // Add a new facet to the index, commit and refresh readers - addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "c", "d"); - writers[0].indexWriter.close(); - writers[0].taxWriter.close(); + addFacets(iParams, indexWriter, taxoWriter, "c", "d"); + IOUtils.close(indexWriter, taxoWriter); - DirectoryTaxonomyReader newTaxoReader = TaxonomyReader.openIfChanged(readers[0].taxReader); + TaxonomyReader newTaxoReader = TaxonomyReader.openIfChanged(taxoReader); assertNotNull(newTaxoReader); - assertTrue("should have received more cagtegories in updated taxonomy", newTaxoReader.getSize() > readers[0].taxReader.getSize()); - readers[0].taxReader.close(); - readers[0].taxReader = newTaxoReader; + assertTrue("should have received more cagtegories in updated taxonomy", newTaxoReader.getSize() > taxoReader.getSize()); + taxoReader.close(); + taxoReader = newTaxoReader; - DirectoryReader r2 = DirectoryReader.openIfChanged(readers[0].indexReader); + DirectoryReader r2 = DirectoryReader.openIfChanged(indexReader); assertNotNull(r2); - readers[0].indexReader.close(); - readers[0].indexReader = r2; + indexReader.close(); + indexReader = r2; // now use the new reader - should recompute - totalCounts = TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); prevGen = assertRecomputed(totalCounts, prevGen, "after updating the index - 7th attempt!"); // try again - should not recompute assertTrue("Should be obtained from cache at 8th attempt",totalCounts == - TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams)); + TFC.getTotalCounts(indexReader, taxoReader, iParams)); - readers[0].close(); + IOUtils.close(indexReader, taxoReader); outputFile.delete(); - IOUtils.close(dirs[0]); + IOUtils.close(indexDir, taxoDir); } private int assertReadFromDisc(TotalFacetCounts totalCounts, int prevGen, String errMsg) { @@ -341,10 +322,12 @@ */ @Test public void testGrowingTaxonomy() throws Exception { - // Create temporary RAMDirectories - Directory[][] dirs = FacetTestUtils.createIndexTaxonomyDirs(1); + Directory indexDir = newDirectory(); + Directory taxoDir = newDirectory(); + // Create our index/taxonomy writers - IndexTaxonomyWriterPair[] writers = FacetTestUtils.createIndexTaxonomyWriterPair(dirs); + IndexWriter indexWriter = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); FacetIndexingParams iParams = new FacetIndexingParams() { @Override public int getPartitionSize() { @@ -352,37 +335,38 @@ } }; // Add a facet to the index - addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "a", "b"); + addFacets(iParams, indexWriter, taxoWriter, "a", "b"); // Commit Changes - writers[0].indexWriter.commit(); - writers[0].taxWriter.commit(); + indexWriter.commit(); + taxoWriter.commit(); - IndexTaxonomyReaderPair[] readers = FacetTestUtils.createIndexTaxonomyReaderPair(dirs); + DirectoryReader indexReader = DirectoryReader.open(indexDir); + TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); // Create TFC and write cache to disk File outputFile = _TestUtil.createTempFile("test", "tmp", TEMP_DIR); - TFC.store(outputFile, readers[0].indexReader, readers[0].taxReader, iParams); + TFC.store(outputFile, indexReader, taxoReader, iParams); // Make the taxonomy grow without touching the index for (int i = 0; i < 10; i++) { - writers[0].taxWriter.addCategory(new CategoryPath("foo", Integer.toString(i))); + taxoWriter.addCategory(new CategoryPath("foo", Integer.toString(i))); } - writers[0].taxWriter.commit(); - DirectoryTaxonomyReader newTaxoReader = TaxonomyReader.openIfChanged(readers[0].taxReader); + taxoWriter.commit(); + TaxonomyReader newTaxoReader = TaxonomyReader.openIfChanged(taxoReader); assertNotNull(newTaxoReader); - readers[0].taxReader.close(); - readers[0].taxReader = newTaxoReader; + taxoReader.close(); + taxoReader = newTaxoReader; initCache(); // With the bug, this next call should result in an exception - TFC.load(outputFile, readers[0].indexReader, readers[0].taxReader, iParams); - TotalFacetCounts totalCounts = TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + TFC.load(outputFile, indexReader, taxoReader, iParams); + TotalFacetCounts totalCounts = TFC.getTotalCounts(indexReader, taxoReader, iParams); assertReadFromDisc(totalCounts, 0, "after reading from disk."); + outputFile.delete(); - writers[0].close(); - readers[0].close(); - IOUtils.close(dirs[0]); + IOUtils.close(indexWriter, taxoWriter, indexReader, taxoReader); + IOUtils.close(indexDir, taxoDir); } /** @@ -445,46 +429,52 @@ */ @Test public void testMultipleIndices() throws IOException { - // Create temporary RAMDirectories - Directory[][] dirs = FacetTestUtils.createIndexTaxonomyDirs(2); + Directory indexDir1 = newDirectory(), indexDir2 = newDirectory(); + Directory taxoDir1 = newDirectory(), taxoDir2 = newDirectory(); + // Create our index/taxonomy writers - IndexTaxonomyWriterPair[] writers = FacetTestUtils.createIndexTaxonomyWriterPair(dirs); + IndexWriter indexWriter1 = new IndexWriter(indexDir1, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); + IndexWriter indexWriter2 = new IndexWriter(indexDir2, newIndexWriterConfig(TEST_VERSION_CURRENT, null)); + TaxonomyWriter taxoWriter1 = new DirectoryTaxonomyWriter(taxoDir1); + TaxonomyWriter taxoWriter2 = new DirectoryTaxonomyWriter(taxoDir2); FacetIndexingParams iParams = FacetIndexingParams.ALL_PARENTS; // Add a facet to the index - addFacets(iParams, writers[0].indexWriter, writers[0].taxWriter, "a", "b"); - addFacets(iParams, writers[1].indexWriter, writers[1].taxWriter, "d", "e"); + addFacets(iParams, indexWriter1, taxoWriter1, "a", "b"); + addFacets(iParams, indexWriter1, taxoWriter1, "d", "e"); // Commit Changes - writers[0].indexWriter.commit(); - writers[0].taxWriter.commit(); - writers[1].indexWriter.commit(); - writers[1].taxWriter.commit(); + indexWriter1.commit(); + indexWriter2.commit(); + taxoWriter1.commit(); + taxoWriter2.commit(); // Open two readers - IndexTaxonomyReaderPair[] readers = FacetTestUtils.createIndexTaxonomyReaderPair(dirs); + DirectoryReader indexReader1 = DirectoryReader.open(indexDir1); + DirectoryReader indexReader2 = DirectoryReader.open(indexDir2); + TaxonomyReader taxoReader1 = new DirectoryTaxonomyReader(taxoDir1); + TaxonomyReader taxoReader2 = new DirectoryTaxonomyReader(taxoDir2); // As this is the first time we have invoked the TotalFacetCountsManager, we // should expect to compute. - TotalFacetCounts totalCounts0 = - TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + TotalFacetCounts totalCounts0 = TFC.getTotalCounts(indexReader1, taxoReader1, iParams); int prevGen = -1; prevGen = assertRecomputed(totalCounts0, prevGen, "after attempt 1"); assertTrue("attempt 1b for same input [0] shout find it in cache", - totalCounts0 == TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams)); + totalCounts0 == TFC.getTotalCounts(indexReader1, taxoReader1, iParams)); // 2nd Reader - As this is the first time we have invoked the // TotalFacetCountsManager, we should expect a state of NEW to be returned. - TotalFacetCounts totalCounts1 = TFC.getTotalCounts(readers[1].indexReader, readers[1].taxReader, iParams); + TotalFacetCounts totalCounts1 = TFC.getTotalCounts(indexReader2, taxoReader2, iParams); prevGen = assertRecomputed(totalCounts1, prevGen, "after attempt 2"); assertTrue("attempt 2b for same input [1] shout find it in cache", - totalCounts1 == TFC.getTotalCounts(readers[1].indexReader, readers[1].taxReader, iParams)); + totalCounts1 == TFC.getTotalCounts(indexReader2, taxoReader2, iParams)); // Right now cache size is one, so first TFC is gone and should be recomputed - totalCounts0 = TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + totalCounts0 = TFC.getTotalCounts(indexReader1, taxoReader1, iParams); prevGen = assertRecomputed(totalCounts0, prevGen, "after attempt 3"); // Similarly will recompute the second result - totalCounts1 = TFC.getTotalCounts(readers[1].indexReader, readers[1].taxReader, iParams); + totalCounts1 = TFC.getTotalCounts(indexReader2, taxoReader2, iParams); prevGen = assertRecomputed(totalCounts1, prevGen, "after attempt 4"); // Now we set the cache size to two, meaning both should exist in the @@ -492,23 +482,19 @@ TFC.setCacheSize(2); // Re-compute totalCounts0 (was evicted from the cache when the cache was smaller) - totalCounts0 = TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams); + totalCounts0 = TFC.getTotalCounts(indexReader1, taxoReader1, iParams); prevGen = assertRecomputed(totalCounts0, prevGen, "after attempt 5"); // now both are in the larger cache and should not be recomputed - totalCounts1 = TFC.getTotalCounts(readers[1].indexReader, readers[1].taxReader, iParams); + totalCounts1 = TFC.getTotalCounts(indexReader2, taxoReader2, iParams); assertTrue("with cache of size 2 res no. 0 should come from cache", - totalCounts0 == TFC.getTotalCounts(readers[0].indexReader, readers[0].taxReader, iParams)); + totalCounts0 == TFC.getTotalCounts(indexReader1, taxoReader1, iParams)); assertTrue("with cache of size 2 res no. 1 should come from cache", - totalCounts1 == TFC.getTotalCounts(readers[1].indexReader, readers[1].taxReader, iParams)); + totalCounts1 == TFC.getTotalCounts(indexReader2, taxoReader2, iParams)); - writers[0].close(); - writers[1].close(); - readers[0].close(); - readers[1].close(); - for (Directory[] dirset : dirs) { - IOUtils.close(dirset); - } + IOUtils.close(indexWriter1, indexWriter2, taxoWriter1, taxoWriter2); + IOUtils.close(indexReader1, indexReader2, taxoReader1, taxoReader2); + IOUtils.close(indexDir1, indexDir2, taxoDir1, taxoDir2); } } Index: lucene/facet/src/test/org/apache/lucene/facet/search/sampling/OversampleWithDepthTest.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/sampling/OversampleWithDepthTest.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/search/sampling/OversampleWithDepthTest.java (working copy) @@ -3,7 +3,6 @@ import java.io.IOException; import java.util.Collections; -import org.apache.lucene.analysis.core.KeywordAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.facet.FacetTestCase; import org.apache.lucene.facet.index.FacetFields; @@ -95,7 +94,7 @@ } private void index100Docs(Directory indexDir, Directory taxoDir, FacetIndexingParams fip) throws IOException { - IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new KeywordAnalyzer()); + IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, null); IndexWriter w = new IndexWriter(indexDir, iwc); TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir); Index: lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java (revision 1440418) +++ lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java (working copy) @@ -3,7 +3,7 @@ import java.io.IOException; import java.util.Random; -import org.apache.lucene.analysis.core.KeywordAnalyzer; +import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.facet.FacetTestCase; import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.TaxonomyReader; @@ -256,7 +256,7 @@ // hold onto IW to forceMerge // note how we don't close it, since DTW will close it. final IndexWriter iw = new IndexWriter(dir, - new IndexWriterConfig(TEST_VERSION_CURRENT, new KeywordAnalyzer()) + new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())) .setMergePolicy(new LogByteSizeMergePolicy())); DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir) { @Override @@ -299,7 +299,7 @@ // hold onto IW to forceMerge // note how we don't close it, since DTW will close it. final IndexWriter iw = new IndexWriter(dir, - new IndexWriterConfig(TEST_VERSION_CURRENT, new KeywordAnalyzer()) + new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())) .setMergePolicy(new LogByteSizeMergePolicy())); DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir) { @Override