利用lucene开发了一个文档检索系统,大量用到了facet功能,发现系统性能出现问题,就想研究一下lucene的facet功能是如何实现了,网络参考资料甚少,google有被某d屏蔽,就阅读了facet部分功能代码,似乎有所启发,担心忘记,记录如下:
IndexWriterindexWriter = new IndexWriter(indexDir, new IndexWriterConfig(FacetExamples.EXAMPLES_VER,
newWhitespaceAnalyzer(FacetExamples.EXAMPLES_VER)));
// Writes facet ords to a separatedirectory from the main index
DirectoryTaxonomyWriter taxoWriter = newDirectoryTaxonomyWriter(taxoDir);
Document doc = new Document();
doc.add(newFacetField("Author", "Bob"));
doc.add(new FacetField("PublishDate", "2010", "10", "15"));
indexWriter.addDocument(config.build(taxoWriter, doc));
doc = new Document();
doc.add(new FacetField("Author","Lisa"));
doc.add(new FacetField("PublishDate", "2010", "10", "20"));
indexWriter.addDocument(config.build(taxoWriter, doc));
doc = new Document();
doc.add(new FacetField("Author","Lisa"));
doc.add(new FacetField("PublishDate", "2012", "1", "1"));
indexWriter.addDocument(config.build(taxoWriter, doc));
doc = new Document();
doc.add(new FacetField("Author","Susan"));
doc.add(new FacetField("PublishDate", "2012", "1", "7"));
indexWriter.addDocument(config.build(taxoWriter, doc));
doc = new Document();
doc.add(new FacetField("Author","Frank"));
doc.add(new FacetField("PublishDate", "1999", "5", "5"));
indexWriter.addDocument(config.build(taxoWriter, doc));
facet的统计结果信息事先按照一棵树结构进行存放。
facet统计情况事先构建一棵树进行存储;每个节点包含parent,child,silbing信息;
child存放最后一个child的值,silbing存放左兄弟的值。
facet的信息单独存放在一片索引区域。
0:根
1:author
2:authorbob
3:Publish Date
7:authorLisa
4:Publish Date2010
5:Publish Date201010
6:Publish Date20101015
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Parent:-1 0 1 0 3 4 5 1 5 3 9 10 1 10 1 3 15 16
Child: 3 14 -1 15 5 8 -1 -1-1 10 13 -1 -1 -1 -1 16 17 -1
Silbing:-1 -1 -1 1 -1 -1 -1 2 6 4 -1 -1 7 11 12 9 -1 -1
文档索引时存放doc.add(newBinaryDocValuesField(indexFieldName, new BytesRef(bytes, 0, upto))));(出现在此类FacetsConfig)一个字段,这个字段存放出现上面构造的节点信息,例如第一个文档存放2,6信息,实际写入的为2,4,猜想是按照偏离存放的。
利用如此巧妙的构造就实现了按照字段的统计。
检索时得到命中结果,存放到一个bitset中,即所有文档的01值,出现为1,不出现为0.
然后遍历这个bitset,读取 BinaryDocValuesField存放的值,那个节点出现了就让这个节点的值+1,如此就实现了对检索结果的实时统计。
和我猜想一致大数据量做统计是会耗费一些性能,但是不如我所想的那样大。