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