001    package 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    
020    import java.io.IOException;
021    import java.util.ArrayList;
022    import java.util.List;
023    
024    import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
025    import org.apache.lucene.document.Document;
026    import org.apache.lucene.facet.DrillDownQuery;
027    import org.apache.lucene.facet.DrillSideways.DrillSidewaysResult;
028    import org.apache.lucene.facet.DrillSideways;
029    import org.apache.lucene.facet.FacetField;
030    import org.apache.lucene.facet.FacetResult;
031    import org.apache.lucene.facet.Facets;
032    import org.apache.lucene.facet.FacetsCollector;
033    import org.apache.lucene.facet.FacetsConfig;
034    import org.apache.lucene.facet.taxonomy.FastTaxonomyFacetCounts;
035    import org.apache.lucene.facet.taxonomy.TaxonomyReader;
036    import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
037    import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
038    import org.apache.lucene.index.DirectoryReader;
039    import org.apache.lucene.index.IndexWriter;
040    import org.apache.lucene.index.IndexWriterConfig;
041    import org.apache.lucene.search.IndexSearcher;
042    import org.apache.lucene.search.MatchAllDocsQuery;
043    import org.apache.lucene.store.Directory;
044    import org.apache.lucene.store.RAMDirectory;
045    
046    /** Shows simple usage of faceted indexing and search. */
047    public class SimpleFacetsExample {
048    
049      private final Directory indexDir = new RAMDirectory();
050      private final Directory taxoDir = new RAMDirectory();
051      private final FacetsConfig config = new FacetsConfig();
052    
053      /** Empty constructor */
054      public SimpleFacetsExample() {
055        config.setHierarchical("Publish Date", true);
056      }
057      
058      /** Build the example index. */
059      private void index() throws IOException {
060        IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(FacetExamples.EXAMPLES_VER, 
061            new WhitespaceAnalyzer(FacetExamples.EXAMPLES_VER)));
062    
063        // Writes facet ords to a separate directory from the main index
064        DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
065    
066        Document doc = new Document();
067        doc.add(new FacetField("Author", "Bob"));
068        doc.add(new FacetField("Publish Date", "2010", "10", "15"));
069        indexWriter.addDocument(config.build(taxoWriter, doc));
070    
071        doc = new Document();
072        doc.add(new FacetField("Author", "Lisa"));
073        doc.add(new FacetField("Publish Date", "2010", "10", "20"));
074        indexWriter.addDocument(config.build(taxoWriter, doc));
075    
076        doc = new Document();
077        doc.add(new FacetField("Author", "Lisa"));
078        doc.add(new FacetField("Publish Date", "2012", "1", "1"));
079        indexWriter.addDocument(config.build(taxoWriter, doc));
080    
081        doc = new Document();
082        doc.add(new FacetField("Author", "Susan"));
083        doc.add(new FacetField("Publish Date", "2012", "1", "7"));
084        indexWriter.addDocument(config.build(taxoWriter, doc));
085    
086        doc = new Document();
087        doc.add(new FacetField("Author", "Frank"));
088        doc.add(new FacetField("Publish Date", "1999", "5", "5"));
089        indexWriter.addDocument(config.build(taxoWriter, doc));
090        
091        indexWriter.close();
092        taxoWriter.close();
093      }
094    
095      /** User runs a query and counts facets. */
096      private List<FacetResult> search() throws IOException {
097        DirectoryReader indexReader = DirectoryReader.open(indexDir);
098        IndexSearcher searcher = new IndexSearcher(indexReader);
099        TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
100    
101        FacetsCollector fc = new FacetsCollector();
102    
103        // MatchAllDocsQuery is for "browsing" (counts facets
104        // for all non-deleted docs in the index); normally
105        // you'd use a "normal" query:
106        FacetsCollector.search(searcher, new MatchAllDocsQuery(), 10, fc);
107    
108        // Retrieve results
109        List<FacetResult> results = new ArrayList<FacetResult>();
110    
111        // Count both "Publish Date" and "Author" dimensions
112        Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, fc);
113        results.add(facets.getTopChildren(10, "Author"));
114        results.add(facets.getTopChildren(10, "Publish Date"));
115        
116        indexReader.close();
117        taxoReader.close();
118        
119        return results;
120      }
121      
122      /** User drills down on 'Publish Date/2010', and we
123       *  return facets for 'Author' */
124      private FacetResult drillDown() throws IOException {
125        DirectoryReader indexReader = DirectoryReader.open(indexDir);
126        IndexSearcher searcher = new IndexSearcher(indexReader);
127        TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
128    
129        // Passing no baseQuery means we drill down on all
130        // documents ("browse only"):
131        DrillDownQuery q = new DrillDownQuery(config);
132    
133        // Now user drills down on Publish Date/2010:
134        q.add("Publish Date", "2010");
135        FacetsCollector fc = new FacetsCollector();
136        FacetsCollector.search(searcher, q, 10, fc);
137    
138        // Retrieve results
139        Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, fc);
140        FacetResult result = facets.getTopChildren(10, "Author");
141    
142        indexReader.close();
143        taxoReader.close();
144        
145        return result;
146      }
147    
148      /** User drills down on 'Publish Date/2010', and we
149       *  return facets for both 'Publish Date' and 'Author',
150       *  using DrillSideways. */
151      private List<FacetResult> drillSideways() throws IOException {
152        DirectoryReader indexReader = DirectoryReader.open(indexDir);
153        IndexSearcher searcher = new IndexSearcher(indexReader);
154        TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
155    
156        // Passing no baseQuery means we drill down on all
157        // documents ("browse only"):
158        DrillDownQuery q = new DrillDownQuery(config);
159    
160        // Now user drills down on Publish Date/2010:
161        q.add("Publish Date", "2010");
162    
163        DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
164        DrillSidewaysResult result = ds.search(q, 10);
165    
166        // Retrieve results
167        List<FacetResult> facets = result.facets.getAllDims(10);
168    
169        indexReader.close();
170        taxoReader.close();
171        
172        return facets;
173      }
174    
175      /** Runs the search example. */
176      public List<FacetResult> runSearch() throws IOException {
177        index();
178        return search();
179      }
180      
181      /** Runs the drill-down example. */
182      public FacetResult runDrillDown() throws IOException {
183        index();
184        return drillDown();
185      }
186    
187      /** Runs the drill-sideways example. */
188      public List<FacetResult> runDrillSideways() throws IOException {
189        index();
190        return drillSideways();
191      }
192    
193      /** Runs the search and drill-down examples and prints the results. */
194      public static void main(String[] args) throws Exception {
195        System.out.println("Facet counting example:");
196        System.out.println("-----------------------");
197        SimpleFacetsExample example = new SimpleFacetsExample();
198        List<FacetResult> results = example.runSearch();
199        System.out.println("Author: " + results.get(0));
200        System.out.println("Publish Date: " + results.get(1));
201        System.out.println("\n");
202        System.out.println("Facet drill-down example (Publish Date/2010):");
203        System.out.println("---------------------------------------------");
204        System.out.println("Author: " + example.runDrillDown());
205    
206        System.out.println("\n");
207        System.out.println("Facet drill-sideways example (Publish Date/2010):");
208        System.out.println("---------------------------------------------");
209        for(FacetResult result : example.runDrillSideways()) {
210          System.out.println(result);
211        }
212      }
213      
214    }