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}