使用 Lucene 按类别对结果进行计数
我正在尝试使用Lucene Java 2.3.2来实现对产品目录的搜索。除了产品的常规字段外,还有一个名为“类别”的字段。一个产品可以分为多个类别。目前,我使用FilteredQuery在每个类别中搜索相同的搜索词,以获取每个类别的结果数。
这将导致每个查询进行 20-30 次内部搜索调用以显示结果。这大大减慢了搜索速度。有没有一种更快的方法可以使用Lucene获得相同的结果?
我正在尝试使用Lucene Java 2.3.2来实现对产品目录的搜索。除了产品的常规字段外,还有一个名为“类别”的字段。一个产品可以分为多个类别。目前,我使用FilteredQuery在每个类别中搜索相同的搜索词,以获取每个类别的结果数。
这将导致每个查询进行 20-30 次内部搜索调用以显示结果。这大大减慢了搜索速度。有没有一种更快的方法可以使用Lucene获得相同的结果?
以下是我所做的,尽管它有点内存过重:
您需要的是提前创建一堆 BitSet
s,每个类别一个,其中包含一个类别中所有文档的文档 ID。现在,在搜索时,您可以使用 HitCollector 并根据 BitSet 检查文档 ID。
下面是创建位集的代码:
public BitSet[] getBitSets(IndexSearcher indexSearcher,
Category[] categories) {
BitSet[] bitSets = new BitSet[categories.length];
for(int i=0; i<categories.length; i++)
{
Query query = categories[i].getQuery();
final BitSet bitset = new BitSet()
indexSearcher.search(query, new HitCollector() {
public void collect(int doc, float score) {
bitSet.set(doc);
}
});
bitSets[i] = bitSet;
}
return bitSets;
}
这只是实现这一目标的一种方法。如果您的类别足够简单,则可以使用 TermDocs 而不是运行完整搜索,但无论如何,当您加载索引时,这应该只运行一次。
现在,当需要计算搜索结果的类别时,您可以执行以下操作:
public int[] getCategroryCount(IndexSearcher indexSearcher,
Query query,
final BitSet[] bitSets) {
final int[] count = new int[bitSets.length];
indexSearcher.search(query, new HitCollector() {
public void collect(int doc, float score) {
for(int i=0; i<bitSets.length; i++) {
if(bitSets[i].get(doc)) count[i]++;
}
}
});
return count;
}
您最终得到的是一个数组,其中包含搜索结果中每个类别的计数。如果您还需要搜索结果,则应将TopDocCollector添加到您的热门收集器中(yo dawg...)。或者,您可以再次运行搜索。2 个搜索优于 30 个。
我没有足够的声誉来评论(!),但在Matt Quail的答案中,我很确定你可以替换这个:
int numDocs = 0;
td.seek(terms);
while (td.next()) {
numDocs++;
}
有了这个:
int numDocs = terms.docFreq()
然后完全摆脱td变量。这应该使它更快。