    001package org.apache.lucene.demo.facet;
    002
    003import java.io.IOException;
    004import java.util.ArrayList;
    005import java.util.HashMap;
    006import java.util.List;
    007import java.util.Map;
    008
    009import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
    010import org.apache.lucene.document.Document;
    011import org.apache.lucene.facet.index.FacetFields;
    012import org.apache.lucene.facet.params.CategoryListParams;
    013import org.apache.lucene.facet.params.FacetIndexingParams;
    014import org.apache.lucene.facet.params.FacetSearchParams;
    015import org.apache.lucene.facet.params.PerDimensionIndexingParams;
    016import org.apache.lucene.facet.search.CountFacetRequest;
    017import org.apache.lucene.facet.search.FacetResult;
    018import org.apache.lucene.facet.search.FacetsCollector;
    019import org.apache.lucene.facet.taxonomy.CategoryPath;
    020import org.apache.lucene.facet.taxonomy.TaxonomyReader;
    021import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
    022import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
    023import org.apache.lucene.index.DirectoryReader;
    024import org.apache.lucene.index.IndexWriter;
    025import org.apache.lucene.index.IndexWriterConfig;
    026import org.apache.lucene.search.IndexSearcher;
    027import org.apache.lucene.search.MatchAllDocsQuery;
    028import org.apache.lucene.store.Directory;
    029import 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. */
    049public 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}