Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java (revision 0) +++ lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java (working copy) @@ -0,0 +1,110 @@ +package org.apache.lucene.facet.search; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.PayloadFacetField; +import org.apache.lucene.facet.search.params.CountFacetRequest; +import org.apache.lucene.facet.search.params.FacetSearchParams; +import org.apache.lucene.facet.search.results.FacetResult; +import org.apache.lucene.facet.search.results.FacetResultNode; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyReader; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; +import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MatchAllDocsQuery; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.LuceneTestCase; + +public class TestDemoFacets extends LuceneTestCase { + + private DirectoryTaxonomyWriter taxoWriter; + private RandomIndexWriter writer; + + private void add(String ... categoryPaths) throws IOException { + Document doc = new Document(); + + List paths = new ArrayList(); + for(String categoryPath : categoryPaths) { + CategoryPath cp = new CategoryPath(categoryPath, '/'); + paths.add(cp); + //int ord = taxoWriter.addCategory(cp); + //doc.add(new PackedLongDocValuesField(cp.getComponent(0), ord)); + } + doc.add(new PayloadFacetField(paths, taxoWriter)); + //CategoryDocumentBuilder docBuilder = new CategoryDocumentBuilder(taxoWriter); + //docBuilder.setCategoryPaths(paths); + //docBuilder.build(doc); + writer.addDocument(doc); + } + + public void test() throws Exception { + Directory dir = newDirectory(); + Directory taxoDir = newDirectory(); + writer = new RandomIndexWriter(random(), dir); + taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode.CREATE); + + add("Author/Bob", "Publish Date/2010/10/15"); + add("Author/Lisa", "Publish Date/2010/10/20"); + add("Author/Lisa", "Publish Date/2012/1/1"); + add("Author/Susan", "Publish Date/2012/1/7"); + add("Author/Frank", "Publish Date/1999/5/5"); + + IndexSearcher searcher = newSearcher(writer.getReader()); + writer.close(); + + TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter); + taxoWriter.close(); + + FacetSearchParams fsp = new FacetSearchParams(); + fsp.addFacetRequest(new CountFacetRequest(new CategoryPath("Publish Date"), 10)); + fsp.addFacetRequest(new CountFacetRequest(new CategoryPath("Author"), 10)); + FacetsCollector c = new FacetsCollector(fsp, searcher.getIndexReader(), taxoReader); + searcher.search(new MatchAllDocsQuery(), c); + List results = c.getFacetResults(); + assertEquals("Publish Date (5)\n 2012 (2)\n 2010 (2)\n 1999 (1)\n", + toSimpleString(results.get(0))); + assertEquals("Author (5)\n Lisa (2)\n Frank (1)\n Susan (1)\n Bob (1)\n", + toSimpleString(results.get(1))); + + taxoReader.close(); + searcher.getIndexReader().close(); + dir.close(); + taxoDir.close(); + } + + private String toSimpleString(FacetResult fr) { + StringBuilder sb = new StringBuilder(); + toSimpleString(0, sb, fr.getFacetResultNode(), ""); + return sb.toString(); + } + + private void toSimpleString(int depth, StringBuilder sb, FacetResultNode node, String indent) { + sb.append(indent + node.getLabel().getComponent(depth) + " (" + (int) node.getValue() + ")\n"); + for(FacetResultNode childNode : node.getSubResults()) { + toSimpleString(depth+1, sb, childNode, indent + " "); + } + } +} Property changes on: lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/facet/src/java/org/apache/lucene/document/PayloadFacetField.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/document/PayloadFacetField.java (revision 0) +++ lucene/facet/src/java/org/apache/lucene/document/PayloadFacetField.java (working copy) @@ -0,0 +1,86 @@ +package org.apache.lucene.document; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.apache.lucene.facet.index.attributes.CategoryAttribute; +import org.apache.lucene.facet.index.attributes.CategoryAttributeImpl; +import org.apache.lucene.facet.index.params.CategoryListParams; +import org.apache.lucene.facet.index.params.DefaultFacetIndexingParams; +import org.apache.lucene.facet.index.params.FacetIndexingParams; +import org.apache.lucene.facet.index.streaming.CategoryAttributesStream; +import org.apache.lucene.facet.index.streaming.CategoryListTokenizer; +import org.apache.lucene.facet.index.streaming.CategoryParentsStream; +import org.apache.lucene.facet.index.streaming.CategoryTokenizer; +import org.apache.lucene.facet.index.streaming.CountingListTokenizer; +import org.apache.lucene.facet.taxonomy.CategoryPath; +import org.apache.lucene.facet.taxonomy.TaxonomyWriter; +import org.apache.lucene.index.Term; + +// nocommit what happens if you add more than one of these +// fields to the index...? hmm multiple positions ... hmm +// nocommit single-valued/multi-valued? + +/** Sugar for the common case; use {@link + * CategoryDocumentBuilder} for expert cases. */ +public class PayloadFacetField extends Field { + + // nocommit is this safe? does it have mutable state? + private static final FacetIndexingParams DEFAULT_FACET_INDEXING_PARAMS = new DefaultFacetIndexingParams(); + + public static final FieldType TYPE = new FieldType(TextField.TYPE_NOT_STORED); + + static { + TYPE.setOmitNorms(true); + TYPE.freeze(); + } + + public PayloadFacetField(Iterable paths, TaxonomyWriter taxoWriter) { + this(DEFAULT_FACET_INDEXING_PARAMS, paths, taxoWriter); + } + + public PayloadFacetField(FacetIndexingParams indexingParams, Iterable categoryPaths, TaxonomyWriter taxoWriter) { + super(CategoryListParams.DEFAULT_TERM.field(), TYPE); + + List atts = new ArrayList(); + for(CategoryPath categoryPath : categoryPaths) { + Term term = indexingParams.getCategoryListParams(categoryPath).getTerm(); + if (!term.field().equals(CategoryListParams.DEFAULT_TERM.field())) { + // nocommit improve message: what configuration of + // FIP would result in different field names + // ... partitioning (or is that just different terms + // w/in same field...). + throw new IllegalArgumentException("ust CategoryDocumentBuilder instead"); + } + atts.add(new CategoryAttributeImpl(categoryPath)); + } + + CategoryAttributesStream categoryAttributesStream = new CategoryAttributesStream(atts); + // Set a suitable {@link TokenStream} using + // CategoryParentsStream, followed by CategoryListTokenizer and + // CategoryTokenizer composition (the ordering of the last two is + // not mandatory). + CategoryParentsStream parentsStream = new CategoryParentsStream(categoryAttributesStream, + taxoWriter, indexingParams); + CategoryListTokenizer categoryListTokenizer = new CountingListTokenizer(parentsStream, indexingParams); + CategoryTokenizer stream = new CategoryTokenizer(categoryListTokenizer, indexingParams); + setTokenStream(stream); + } +} Property changes on: lucene/facet/src/java/org/apache/lucene/document/PayloadFacetField.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property