001package org.apache.lucene.demo.facet;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements.  See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020import java.io.IOException;
021import java.util.ArrayList;
022import java.util.List;
023
024import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
025import org.apache.lucene.document.Document;
026import org.apache.lucene.facet.params.FacetSearchParams;
027import org.apache.lucene.facet.search.CountFacetRequest;
028import org.apache.lucene.facet.search.DrillDownQuery;
029import org.apache.lucene.facet.search.FacetResult;
030import org.apache.lucene.facet.search.FacetsCollector;
031import org.apache.lucene.facet.sortedset.SortedSetDocValuesAccumulator;
032import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetFields;
033import org.apache.lucene.facet.sortedset.SortedSetDocValuesReaderState;
034import org.apache.lucene.facet.taxonomy.CategoryPath;
035import org.apache.lucene.index.DirectoryReader;
036import org.apache.lucene.index.IndexWriter;
037import org.apache.lucene.index.IndexWriterConfig;
038import org.apache.lucene.search.IndexSearcher;
039import org.apache.lucene.search.MatchAllDocsQuery;
040import org.apache.lucene.store.Directory;
041import org.apache.lucene.store.RAMDirectory;
042
043/** Shows simple usage of faceted indexing and search,
044 *  using {@link SortedSetDocValuesFacetFields} and {@link
045 *  SortedSetDocValuesAccumulator}.  */
046
047public class SimpleSortedSetFacetsExample {
048
049  private final Directory indexDir = new RAMDirectory();
050
051  /** Empty constructor */
052  public SimpleSortedSetFacetsExample() {}
053  
054  private void add(IndexWriter indexWriter, SortedSetDocValuesFacetFields facetFields, String ... categoryPaths) throws IOException {
055    Document doc = new Document();
056    
057    List<CategoryPath> paths = new ArrayList<CategoryPath>();
058    for (String categoryPath : categoryPaths) {
059      paths.add(new CategoryPath(categoryPath, '/'));
060    }
061    facetFields.addFields(doc, paths);
062    indexWriter.addDocument(doc);
063  }
064
065  /** Build the example index. */
066  private void index() throws IOException {
067    IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(FacetExamples.EXAMPLES_VER, 
068        new WhitespaceAnalyzer(FacetExamples.EXAMPLES_VER)));
069
070    // Reused across documents, to add the necessary facet fields
071    SortedSetDocValuesFacetFields facetFields = new SortedSetDocValuesFacetFields();
072
073    add(indexWriter, facetFields, "Author/Bob", "Publish Year/2010");
074    add(indexWriter, facetFields, "Author/Lisa", "Publish Year/2010");
075    add(indexWriter, facetFields, "Author/Lisa", "Publish Year/2012");
076    add(indexWriter, facetFields, "Author/Susan", "Publish Year/2012");
077    add(indexWriter, facetFields, "Author/Frank", "Publish Year/1999");
078    
079    indexWriter.close();
080  }
081
082  /** User runs a query and counts facets. */
083  private List<FacetResult> search() throws IOException {
084    DirectoryReader indexReader = DirectoryReader.open(indexDir);
085    IndexSearcher searcher = new IndexSearcher(indexReader);
086    SortedSetDocValuesReaderState state = new SortedSetDocValuesReaderState(indexReader);
087
088    // Count both "Publish Year" and "Author" dimensions
089    FacetSearchParams fsp = new FacetSearchParams(
090        new CountFacetRequest(new CategoryPath("Publish Year"), 10), 
091        new CountFacetRequest(new CategoryPath("Author"), 10));
092
093    // Aggregatses the facet counts
094    FacetsCollector fc = FacetsCollector.create(new SortedSetDocValuesAccumulator(fsp, state));
095
096    // MatchAllDocsQuery is for "browsing" (counts facets
097    // for all non-deleted docs in the index); normally
098    // you'd use a "normal" query, and use MultiCollector to
099    // wrap collecting the "normal" hits and also facets:
100    searcher.search(new MatchAllDocsQuery(), fc);
101
102    // Retrieve results
103    List<FacetResult> facetResults = fc.getFacetResults();
104    
105    indexReader.close();
106    
107    return facetResults;
108  }
109  
110  /** User drills down on 'Publish Year/2010'. */
111  private List<FacetResult> drillDown() throws IOException {
112    DirectoryReader indexReader = DirectoryReader.open(indexDir);
113    IndexSearcher searcher = new IndexSearcher(indexReader);
114    SortedSetDocValuesReaderState state = new SortedSetDocValuesReaderState(indexReader);
115
116    // Now user drills down on Publish Year/2010:
117    FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(new CategoryPath("Author"), 10));
118    DrillDownQuery q = new DrillDownQuery(fsp.indexingParams, new MatchAllDocsQuery());
119    q.add(new CategoryPath("Publish Year/2010", '/'));
120    FacetsCollector fc = FacetsCollector.create(new SortedSetDocValuesAccumulator(fsp, state));
121    searcher.search(q, fc);
122
123    // Retrieve results
124    List<FacetResult> facetResults = fc.getFacetResults();
125    
126    indexReader.close();
127    
128    return facetResults;
129  }
130
131  /** Runs the search example. */
132  public List<FacetResult> runSearch() throws IOException {
133    index();
134    return search();
135  }
136  
137  /** Runs the drill-down example. */
138  public List<FacetResult> runDrillDown() throws IOException {
139    index();
140    return drillDown();
141  }
142
143  /** Runs the search and drill-down examples and prints the results. */
144  public static void main(String[] args) throws Exception {
145    System.out.println("Facet counting example:");
146    System.out.println("-----------------------");
147    List<FacetResult> results = new SimpleSortedSetFacetsExample().runSearch();
148    for (FacetResult res : results) {
149      System.out.println(res);
150    }
151
152    System.out.println("\n");
153    System.out.println("Facet drill-down example (Publish Year/2010):");
154    System.out.println("---------------------------------------------");
155    results = new SimpleSortedSetFacetsExample().runDrillDown();
156    for (FacetResult res : results) {
157      System.out.println(res);
158    }
159  }
160  
161}