    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.params.FacetSearchParams;
    027    import org.apache.lucene.facet.search.CountFacetRequest;
    028    import org.apache.lucene.facet.search.DrillDownQuery;
    029    import org.apache.lucene.facet.search.FacetResult;
    030    import org.apache.lucene.facet.search.FacetsCollector;
    031    import org.apache.lucene.facet.sortedset.SortedSetDocValuesAccumulator;
    032    import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetFields;
    033    import org.apache.lucene.facet.sortedset.SortedSetDocValuesReaderState;
    034    import org.apache.lucene.facet.taxonomy.CategoryPath;
    035    import org.apache.lucene.index.DirectoryReader;
    036    import org.apache.lucene.index.IndexWriter;
    037    import org.apache.lucene.index.IndexWriterConfig;
    038    import org.apache.lucene.search.IndexSearcher;
    039    import org.apache.lucene.search.MatchAllDocsQuery;
    040    import org.apache.lucene.store.Directory;
    041    import org.apache.lucene.store.RAMDirectory;
    042
    043    /** Shows simple usage of faceted indexing and search,
    044     *  using {@link SortedSetDocValuesFacetFields} and {@link
    045     *  SortedSetDocValuesAccumulator}.  */
    046
    047    public 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    }