Lucene - 如何在给定 parent docID 的情况下获取 parent 块中的所有 child 文档

Lucene - how to get all child docs in a parent's block given a parent docID

我直接使用 Lucene(没有 Solr 或 ElasticSearch)来索引一组遵循 parent-child 层次结构的文档。

我正在使用 'blocks' 通过将所有 children 后跟 parent 添加到同一块调用来完成此操作:

writer.addDocuments(childrenAndParentDocList)

我正在对所有 parents 和 children 进行自由文本搜索(在 child 搜索中使用 ToParentBlockJoinQuery 到 link 直到 parent 文档),它返回一组很好的 parent 文档,这些文档要么匹配查询,要么有一个 child 匹配查询。

接下来我需要做的是获取 all children for all of the parent 我拥有的文件。

我在 lucene 测试 here 中看到了一个方法,它展示了如何在给定 child 文档的情况下获取 parent 文档。

  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));
  }

但我不确定如何做相反的事情。即如何在给定 parent 文档的情况下获取所有 children。

如有任何建议,我们将不胜感激。

我最终使用了下面的代码。它似乎有效:

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;
}

根据你的回答,我做了一个函数的 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;
}