001    package org.apache.lucene.demo.facet;
002    
003    import java.io.IOException;
004    import java.util.ArrayList;
005    import java.util.HashMap;
006    import java.util.List;
007    import java.util.Map;
008    
009    import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
010    import org.apache.lucene.document.Document;
011    import org.apache.lucene.facet.index.FacetFields;
012    import org.apache.lucene.facet.params.CategoryListParams;
013    import org.apache.lucene.facet.params.FacetIndexingParams;
014    import org.apache.lucene.facet.params.FacetSearchParams;
015    import org.apache.lucene.facet.params.PerDimensionIndexingParams;
016    import org.apache.lucene.facet.search.CountFacetRequest;
017    import org.apache.lucene.facet.search.FacetResult;
018    import org.apache.lucene.facet.search.FacetsCollector;
019    import org.apache.lucene.facet.taxonomy.CategoryPath;
020    import org.apache.lucene.facet.taxonomy.TaxonomyReader;
021    import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
022    import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
023    import org.apache.lucene.index.DirectoryReader;
024    import org.apache.lucene.index.IndexWriter;
025    import org.apache.lucene.index.IndexWriterConfig;
026    import org.apache.lucene.search.IndexSearcher;
027    import org.apache.lucene.search.MatchAllDocsQuery;
028    import org.apache.lucene.store.Directory;
029    import org.apache.lucene.store.RAMDirectory;
030    
031    /*
032     * Licensed to the Apache Software Foundation (ASF) under one or more
033     * contributor license agreements.  See the NOTICE file distributed with
034     * this work for additional information regarding copyright ownership.
035     * The ASF licenses this file to You under the Apache License, Version 2.0
036     * (the "License"); you may not use this file except in compliance with
037     * the License.  You may obtain a copy of the License at
038     *
039     *     http://www.apache.org/licenses/LICENSE-2.0
040     *
041     * Unless required by applicable law or agreed to in writing, software
042     * distributed under the License is distributed on an "AS IS" BASIS,
043     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
044     * See the License for the specific language governing permissions and
045     * limitations under the License.
046     */
047    
048    /** Demonstrates indexing categories into different category lists. */
049    public class MultiCategoryListsFacetsExample {
050    
051      private final FacetIndexingParams indexingParams;
052      private final Directory indexDir = new RAMDirectory();
053      private final Directory taxoDir = new RAMDirectory();
054    
055      /** Creates a new instance and populates the catetory list params mapping. */
056      public MultiCategoryListsFacetsExample() {
057        // index all Author facets in one category list and all Publish Date in another.
058        Map<CategoryPath,CategoryListParams> categoryListParams = new HashMap<CategoryPath,CategoryListParams>();
059        categoryListParams.put(new CategoryPath("Author"), new CategoryListParams("author"));
060        categoryListParams.put(new CategoryPath("Publish Date"), new CategoryListParams("pubdate"));
061        indexingParams = new PerDimensionIndexingParams(categoryListParams);
062      }
063      
064      private void add(IndexWriter indexWriter, FacetFields facetFields, String ... categoryPaths) throws IOException {
065        Document doc = new Document();
066        
067        List<CategoryPath> paths = new ArrayList<CategoryPath>();
068        for (String categoryPath : categoryPaths) {
069          paths.add(new CategoryPath(categoryPath, '/'));
070        }
071        facetFields.addFields(doc, paths);
072        indexWriter.addDocument(doc);
073      }
074    
075      /** Build the example index. */
076      private void index() throws IOException {
077        IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(FacetExamples.EXAMPLES_VER, 
078            new WhitespaceAnalyzer(FacetExamples.EXAMPLES_VER)));
079    
080        // Writes facet ords to a separate directory from the main index
081        DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode.CREATE);
082    
083        // Reused across documents, to add the necessary facet fields
084        FacetFields facetFields = new FacetFields(taxoWriter, indexingParams);
085    
086        add(indexWriter, facetFields, "Author/Bob", "Publish Date/2010/10/15");
087        add(indexWriter, facetFields, "Author/Lisa", "Publish Date/2010/10/20");
088        add(indexWriter, facetFields, "Author/Lisa", "Publish Date/2012/1/1");
089        add(indexWriter, facetFields, "Author/Susan", "Publish Date/2012/1/7");
090        add(indexWriter, facetFields, "Author/Frank", "Publish Date/1999/5/5");
091        
092        indexWriter.close();
093        taxoWriter.close();
094      }
095    
096      /** User runs a query and counts facets. */
097      private List<FacetResult> search() throws IOException {
098        DirectoryReader indexReader = DirectoryReader.open(indexDir);
099        IndexSearcher searcher = new IndexSearcher(indexReader);
100        TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
101    
102        // Count both "Publish Date" and "Author" dimensions
103        FacetSearchParams fsp = new FacetSearchParams(indexingParams,
104            new CountFacetRequest(new CategoryPath("Publish Date"), 10), 
105            new CountFacetRequest(new CategoryPath("Author"), 10));
106    
107        // Aggregatses the facet counts
108        FacetsCollector fc = FacetsCollector.create(fsp, searcher.getIndexReader(), taxoReader);
109    
110        // MatchAllDocsQuery is for "browsing" (counts facets
111        // for all non-deleted docs in the index); normally
112        // you'd use a "normal" query, and use MultiCollector to
113        // wrap collecting the "normal" hits and also facets:
114        searcher.search(new MatchAllDocsQuery(), fc);
115    
116        // Retrieve results
117        List<FacetResult> facetResults = fc.getFacetResults();
118        
119        indexReader.close();
120        taxoReader.close();
121        
122        return facetResults;
123      }
124    
125      /** Runs the search example. */
126      public List<FacetResult> runSearch() throws IOException {
127        index();
128        return search();
129      }
130      
131      /** Runs the search example and prints the results. */
132      public static void main(String[] args) throws Exception {
133        System.out.println("Facet counting over multiple category lists example:");
134        System.out.println("-----------------------");
135        List<FacetResult> results = new MultiCategoryListsFacetsExample().runSearch();
136        for (FacetResult res : results) {
137          System.out.println(res);
138        }
139      }
140      
141    }