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.Closeable;
021    import java.io.IOException;
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.document.Field;
027    import org.apache.lucene.document.LongField;
028    import org.apache.lucene.document.NumericDocValuesField;
029    import org.apache.lucene.facet.params.FacetIndexingParams;
030    import org.apache.lucene.facet.range.LongRange;
031    import org.apache.lucene.facet.range.RangeAccumulator;
032    import org.apache.lucene.facet.range.RangeFacetRequest;
033    import org.apache.lucene.facet.search.DrillDownQuery;
034    import org.apache.lucene.facet.search.FacetResult;
035    import org.apache.lucene.facet.search.FacetsCollector;
036    import org.apache.lucene.index.DirectoryReader;
037    import org.apache.lucene.index.IndexWriter;
038    import org.apache.lucene.index.IndexWriterConfig;
039    import org.apache.lucene.search.IndexSearcher;
040    import org.apache.lucene.search.MatchAllDocsQuery;
041    import org.apache.lucene.search.NumericRangeQuery;
042    import org.apache.lucene.search.TopDocs;
043    import org.apache.lucene.store.Directory;
044    import org.apache.lucene.store.RAMDirectory;
045    
046    
047    /** Shows simple usage of dynamic range faceting. */
048    public class RangeFacetsExample implements Closeable {
049    
050      private final Directory indexDir = new RAMDirectory();
051      private IndexSearcher searcher;
052      private final long nowSec = System.currentTimeMillis();
053    
054      /** Empty constructor */
055      public RangeFacetsExample() {}
056      
057      /** Build the example index. */
058      public void index() throws IOException {
059        IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(FacetExamples.EXAMPLES_VER, 
060            new WhitespaceAnalyzer(FacetExamples.EXAMPLES_VER)));
061    
062        // Add documents with a fake timestamp, 1000 sec before
063        // "now", 2000 sec before "now", ...:
064        for(int i=0;i<100;i++) {
065          Document doc = new Document();
066          long then = nowSec - i * 1000;
067          // Add as doc values field, so we can compute range facets:
068          doc.add(new NumericDocValuesField("timestamp", then));
069          // Add as numeric field so we can drill-down:
070          doc.add(new LongField("timestamp", then, Field.Store.NO));
071          indexWriter.addDocument(doc);
072        }
073    
074        // Open near-real-time searcher
075        searcher = new IndexSearcher(DirectoryReader.open(indexWriter, true));
076        indexWriter.close();
077      }
078    
079      /** User runs a query and counts facets. */
080      public List<FacetResult> search() throws IOException {
081    
082        RangeFacetRequest<LongRange> rangeFacetRequest = new RangeFacetRequest<LongRange>("timestamp",
083                                         new LongRange("Past hour", nowSec-3600, true, nowSec, true),
084                                         new LongRange("Past six hours", nowSec-6*3600, true, nowSec, true),
085                                         new LongRange("Past day", nowSec-24*3600, true, nowSec, true));
086        // Aggregatses the facet counts
087        FacetsCollector fc = FacetsCollector.create(new RangeAccumulator(rangeFacetRequest));
088    
089        // MatchAllDocsQuery is for "browsing" (counts facets
090        // for all non-deleted docs in the index); normally
091        // you'd use a "normal" query, and use MultiCollector to
092        // wrap collecting the "normal" hits and also facets:
093        searcher.search(new MatchAllDocsQuery(), fc);
094    
095        // Retrieve results
096        return fc.getFacetResults();
097      }
098      
099      /** User drills down on the specified range. */
100      public TopDocs drillDown(LongRange range) throws IOException {
101    
102        // Passing no baseQuery means we drill down on all
103        // documents ("browse only"):
104        DrillDownQuery q = new DrillDownQuery(FacetIndexingParams.DEFAULT);
105    
106        // Use FieldCacheRangeFilter; this will use
107        // NumericDocValues:
108        q.add("timestamp", NumericRangeQuery.newLongRange("timestamp", range.min, range.max, range.minInclusive, range.maxInclusive));
109    
110        return searcher.search(q, 10);
111      }
112    
113      @Override
114      public void close() throws IOException {
115        searcher.getIndexReader().close();
116        indexDir.close();
117      }
118    
119      /** Runs the search and drill-down examples and prints the results. */
120      @SuppressWarnings("unchecked")
121      public static void main(String[] args) throws Exception {
122        RangeFacetsExample example = new RangeFacetsExample();
123        example.index();
124    
125        System.out.println("Facet counting example:");
126        System.out.println("-----------------------");
127        List<FacetResult> results = example.search();
128        for (FacetResult res : results) {
129          System.out.println(res);
130        }
131    
132        System.out.println("\n");
133        System.out.println("Facet drill-down example (timestamp/Past six hours):");
134        System.out.println("---------------------------------------------");
135        TopDocs hits = example.drillDown((LongRange) ((RangeFacetRequest<LongRange>) results.get(0).getFacetRequest()).ranges[1]);
136        System.out.println(hits.totalHits + " totalHits");
137    
138        example.close();
139      }
140    }