001    package org.apache.lucene.demo.facet;
002    
003    import java.io.IOException;
004    import java.text.ParseException;
005    
006    import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
007    import org.apache.lucene.document.Document;
008    import org.apache.lucene.document.Field.Store;
009    import org.apache.lucene.document.NumericDocValuesField;
010    import org.apache.lucene.document.TextField;
011    import org.apache.lucene.expressions.Expression;
012    import org.apache.lucene.expressions.SimpleBindings;
013    import org.apache.lucene.expressions.js.JavascriptCompiler;
014    import org.apache.lucene.facet.FacetField;
015    import org.apache.lucene.facet.FacetResult;
016    import org.apache.lucene.facet.Facets;
017    import org.apache.lucene.facet.FacetsCollector;
018    import org.apache.lucene.facet.FacetsConfig;
019    import org.apache.lucene.facet.taxonomy.TaxonomyFacetSumValueSource;
020    import org.apache.lucene.facet.taxonomy.TaxonomyReader;
021    import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
022    import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
023    import org.apache.lucene.index.DirectoryReader;
024    import org.apache.lucene.index.IndexWriter;
025    import org.apache.lucene.index.IndexWriterConfig;
026    import org.apache.lucene.search.IndexSearcher;
027    import org.apache.lucene.search.MatchAllDocsQuery;
028    import org.apache.lucene.search.SortField;
029    import org.apache.lucene.store.Directory;
030    import org.apache.lucene.store.RAMDirectory;
031    
032    /*
033     * Licensed to the Apache Software Foundation (ASF) under one or more
034     * contributor license agreements.  See the NOTICE file distributed with
035     * this work for additional information regarding copyright ownership.
036     * The ASF licenses this file to You under the Apache License, Version 2.0
037     * (the "License"); you may not use this file except in compliance with
038     * the License.  You may obtain a copy of the License at
039     *
040     *     http://www.apache.org/licenses/LICENSE-2.0
041     *
042     * Unless required by applicable law or agreed to in writing, software
043     * distributed under the License is distributed on an "AS IS" BASIS,
044     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
045     * See the License for the specific language governing permissions and
046     * limitations under the License.
047     */
048    
049    /** Shows facets aggregation by an expression. */
050    public class ExpressionAggregationFacetsExample {
051    
052      private final Directory indexDir = new RAMDirectory();
053      private final Directory taxoDir = new RAMDirectory();
054      private final FacetsConfig config = new FacetsConfig();
055    
056      /** Empty constructor */
057      public ExpressionAggregationFacetsExample() {}
058      
059      /** Build the example index. */
060      private void index() throws IOException {
061        IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(FacetExamples.EXAMPLES_VER, 
062            new WhitespaceAnalyzer(FacetExamples.EXAMPLES_VER)));
063    
064        // Writes facet ords to a separate directory from the main index
065        DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
066    
067        Document doc = new Document();
068        doc.add(new TextField("c", "foo bar", Store.NO));
069        doc.add(new NumericDocValuesField("popularity", 5L));
070        doc.add(new FacetField("A", "B"));
071        indexWriter.addDocument(config.build(taxoWriter, doc));
072    
073        doc = new Document();
074        doc.add(new TextField("c", "foo foo bar", Store.NO));
075        doc.add(new NumericDocValuesField("popularity", 3L));
076        doc.add(new FacetField("A", "C"));
077        indexWriter.addDocument(config.build(taxoWriter, doc));
078        
079        indexWriter.close();
080        taxoWriter.close();
081      }
082    
083      /** User runs a query and aggregates facets. */
084      private FacetResult search() throws IOException, ParseException {
085        DirectoryReader indexReader = DirectoryReader.open(indexDir);
086        IndexSearcher searcher = new IndexSearcher(indexReader);
087        TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
088    
089        // Aggregate categories by an expression that combines the document's score
090        // and its popularity field
091        Expression expr = JavascriptCompiler.compile("_score * sqrt(popularity)");
092        SimpleBindings bindings = new SimpleBindings();
093        bindings.add(new SortField("_score", SortField.Type.SCORE)); // the score of the document
094        bindings.add(new SortField("popularity", SortField.Type.LONG)); // the value of the 'popularity' field
095    
096        // Aggregates the facet values
097        FacetsCollector fc = new FacetsCollector(true);
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:
102        FacetsCollector.search(searcher, new MatchAllDocsQuery(), 10, fc);
103    
104        // Retrieve results
105        Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, expr.getValueSource(bindings));
106        FacetResult result = facets.getTopChildren(10, "A");
107        
108        indexReader.close();
109        taxoReader.close();
110        
111        return result;
112      }
113      
114      /** Runs the search example. */
115      public FacetResult runSearch() throws IOException, ParseException {
116        index();
117        return search();
118      }
119      
120      /** Runs the search and drill-down examples and prints the results. */
121      public static void main(String[] args) throws Exception {
122        System.out.println("Facet counting example:");
123        System.out.println("-----------------------");
124        FacetResult result = new ExpressionAggregationFacetsExample().runSearch();
125        System.out.println(result);
126      }
127    }