001package org.apache.lucene.demo.facet; 002 003import java.io.IOException; 004import java.text.ParseException; 005 006import org.apache.lucene.analysis.core.WhitespaceAnalyzer; 007import org.apache.lucene.document.Document; 008import org.apache.lucene.document.Field.Store; 009import org.apache.lucene.document.NumericDocValuesField; 010import org.apache.lucene.document.TextField; 011import org.apache.lucene.expressions.Expression; 012import org.apache.lucene.expressions.SimpleBindings; 013import org.apache.lucene.expressions.js.JavascriptCompiler; 014import org.apache.lucene.facet.FacetField; 015import org.apache.lucene.facet.FacetResult; 016import org.apache.lucene.facet.Facets; 017import org.apache.lucene.facet.FacetsCollector; 018import org.apache.lucene.facet.FacetsConfig; 019import org.apache.lucene.facet.taxonomy.TaxonomyFacetSumValueSource; 020import org.apache.lucene.facet.taxonomy.TaxonomyReader; 021import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; 022import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; 023import org.apache.lucene.index.DirectoryReader; 024import org.apache.lucene.index.IndexWriter; 025import org.apache.lucene.index.IndexWriterConfig; 026import org.apache.lucene.search.IndexSearcher; 027import org.apache.lucene.search.MatchAllDocsQuery; 028import org.apache.lucene.search.SortField; 029import org.apache.lucene.store.Directory; 030import 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. */ 050public 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}