我正在直接使用Lucene(没有Solr或ElasticSearch)来索引一组遵循父子层次结构的文档。
我正在使用“块”来实现此目的,方法是将所有子项及其后的父项添加到同一块调用中:
writer.addDocuments(childrenAndParentDocList)
我正在所有父级和子级之间进行自由文本搜索(使用子级搜索中的ToParentBlockJoinQuery链接到父级文档),这将返回一组不错的父级文档,这些文档要么与查询匹配,要么具有符合查询条件的子级。
下一步,我要做的是为我拥有的所有父文档的 all 个获取 all 个子代。
我已经在Lucene测试here中看到了一种方法,该方法展示了如何在给定子文档的情况下获取父文档。
private Document getParentDoc(IndexReader reader, BitSetProducer parents, int childDocID) throws IOException {
final List<LeafReaderContext> leaves = reader.leaves();
final int subIndex = ReaderUtil.subIndex(childDocID, leaves);
final LeafReaderContext leaf = leaves.get(subIndex);
final BitSet bits = parents.getBitSet(leaf);
return leaf.reader().document(bits.nextSetBit(childDocID - leaf.docBase));
}
但是我不确定如何做相反的事情。即如何获取给定父级文档的所有子级。
任何建议将不胜感激。
答案 0 :(得分:0)
我最终使用了下面的代码。似乎可行:
private List<Integer> getChildDocIds(IndexSearcher indexSearcher, int parentDocId) throws IOException {
//Use a query in QueryBitSetProducer constructor which identifies parent docs
BitSetProducer parentsFilter = new QueryBitSetProducer(new TermQuery(new Term("child", "N")));
IndexReader indexReader = indexSearcher.getIndexReader();
List<LeafReaderContext> leaves = indexReader.leaves();
int subIndex = ReaderUtil.subIndex(parentDocId, leaves);
LeafReaderContext leaf = leaves.get(subIndex);
int localParentDocId = parentDocId - leaf.docBase;
List<Integer> childDocs = new ArrayList<>();
if (localParentDocId == 0) {
//not a parent, or parent has no children
return childDocs;
}
int prevParent = parentsFilter.getBitSet(leaf).prevSetBit(localParentDocId - 1);
for(int childDocIndex = prevParent + 1; childDocIndex < localParentDocId; childDocIndex++) {
childDocs.add(leaf.docBase + childDocIndex);
}
return childDocs;
}
答案 1 :(得分:0)
根据您的回答,我对该函数做了一个c#端口,它似乎也可以工作。
我只需要获取嵌套文档,而无需任何过滤器或查询。
private List<Lucene.Net.Documents.Document> GetNestedDocuments(IndexSearcher searcher, int parentDocId)
{
List<Lucene.Net.Documents.Document> documents = new List<Lucene.Net.Documents.Document>();
int subIndex = ReaderUtil.SubIndex(parentDocId, searcher.IndexReader.Leaves);
var leaf = searcher.IndexReader.Leaves[subIndex];
if (parentDocId > leaf.DocBase)
{
for (var childDocIndex = leaf.DocBase; childDocIndex < parentDocId; childDocIndex++)
{
var childDoc = searcher.Doc(childDocIndex);
documents.Add(childDoc);
}
}
return documents;
}