    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    }