如何从Lucene 3.0.3获得可靠的docid?
我想获取刚刚添加到Lucene索引中的文档的int docid,这样我就可以将其粘贴到过滤器中以更新一个长期查询。我的文档具有唯一的外部id,因此我认为对唯一id执行TermDocs枚举将返回正确的文档,如下所示:如何从Lucene 3.0.3获得可靠的docid?,lucene,Lucene,我想获取刚刚添加到Lucene索引中的文档的int docid,这样我就可以将其粘贴到过滤器中以更新一个长期查询。我的文档具有唯一的外部id,因此我认为对唯一id执行TermDocs枚举将返回正确的文档,如下所示: protected int getDocId(IndexReader reader, String idField, Document doc) throws IOException { String id = doc.get(idField); TermDocs t
protected int getDocId(IndexReader reader, String idField, Document doc) throws IOException {
String id = doc.get(idField);
TermDocs termDocs = reader.termDocs(new Term(idField, id));
int docid = -1;
while (termDocs.next()) {
docid = termDocs.doc();
Document aDoc = reader.document(docid);
String docIdString = aDoc.get(idField);
System.out.println(docIdString + ": " + docid);
}
return docid;
}
不幸的是,这会循环,返回相同的docIdString并增加docid
建议如何获取新添加文档的文档Id,以便在提交文档后立即在筛选器中使用它们?文档的文档Id与Id字段中的值不同。文档ID是一个内部Lucene标识符,您可能不应该访问它。你的领域只是一个领域——你可以称它为“ID”,但Lucene不会对它做任何特别的事情 为什么要手动更新过滤器?提交时,可能会发生合并等情况,因此之前的ID将与之后的ID不同。(这只是一个一般性的例子,你不应该依赖Lucene ID来做任何事情。)所以你不需要仅仅将一个文档添加到过滤器中,你需要更新整个文档 要更新缓存的过滤器,只需运行“foo”查询,并将过滤器与
CachingWrapperFilter
一起使用
编辑:因为您的id字段只是一个字段,所以您可以像搜索其他任何内容一样搜索它:
TopDocs results = searcher.Search(new TermQuery(new Term("MyIDField", Id)), 1);
int internalId = results.scoreDocs[0].doc;
但是,正如我所说,我认为您应该忽略内部ID。因此,我将根据查询构建一个过滤器:
BooleanQuery filterQuery = new BooleanQuery(); // or get existing query from cache
filterQuery.Add(new TermQuery(new Term("MyIdField", Id)), BooleanClause.Occur.SHOULD);
// add more sub queries for each ID you want in the filter here
Filter myFilter = new CachingWrapperFilter(new QueryWrapperFilter(filterQuery));
文档的文档Id与Id字段中的值不同。文档ID是一个内部Lucene标识符,您可能不应该访问它。你的领域只是一个领域——你可以称它为“ID”,但Lucene不会对它做任何特别的事情 为什么要手动更新过滤器?提交时,可能会发生合并等情况,因此之前的ID将与之后的ID不同。(这只是一个一般性的例子,你不应该依赖Lucene ID来做任何事情。)所以你不需要仅仅将一个文档添加到过滤器中,你需要更新整个文档 要更新缓存的过滤器,只需运行“foo”查询,并将过滤器与
CachingWrapperFilter
一起使用
编辑:因为您的id字段只是一个字段,所以您可以像搜索其他任何内容一样搜索它:
TopDocs results = searcher.Search(new TermQuery(new Term("MyIDField", Id)), 1);
int internalId = results.scoreDocs[0].doc;
但是,正如我所说,我认为您应该忽略内部ID。因此,我将根据查询构建一个过滤器:
BooleanQuery filterQuery = new BooleanQuery(); // or get existing query from cache
filterQuery.Add(new TermQuery(new Term("MyIdField", Id)), BooleanClause.Occur.SHOULD);
// add more sub queries for each ID you want in the filter here
Filter myFilter = new CachingWrapperFilter(new QueryWrapperFilter(filterQuery));
在添加新文档时,我可能要评估数千个长期查询。我不想在整个集合上重新运行它们,因为我应该能够对缓存在别处的每个查询的结果进行增量更新。CachingWrapperfilter感觉不太对:它将缓存旧结果,但不会缓存新文档。似乎docid应该有足够的持续时间来满足我的目的,但也许我误解了它们的定义。@Gene Golovchinsky:Lucene-IDs。你能试着手动告诉他们什么时候改变吗?当然但是你为了最小的收益而做了很多工作。我建议你确实要确保你的过滤方式是至关重要的——如果你只使用缓存过滤器,它将在99.9999%的时间内工作。过早优化是万恶之源。谢谢你的建议!实际上,我并没有试图持久化docid。我将根据上面的示例代码持久化外部ID,在给定的时间点——在任何commit()或optimize()调用之间——我希望将外部ID转换为相应的docID,构建一个过滤器并使用它。我遇到的问题是,我没有从转换步骤中获得预期的结果。也许我没有使用正确的方法将外部ID转换为docID。@Gene Golovchinsky:我添加了一些代码,可能会有所帮助。正如我所说,你之前遇到的问题是Lucene的文档ID!=您的id字段的值,因此您不能通过切换它们的值来枚举。我可能有数千个长期查询,我希望在添加新文档时对这些查询进行评估。我不想在整个集合上重新运行它们,因为我应该能够对缓存在别处的每个查询的结果进行增量更新。CachingWrapperfilter感觉不太对:它将缓存旧结果,但不会缓存新文档。似乎docid应该有足够的持续时间来满足我的目的,但也许我误解了它们的定义。@Gene Golovchinsky:Lucene-IDs。你能试着手动告诉他们什么时候改变吗?当然但是你为了最小的收益而做了很多工作。我建议你确实要确保你的过滤方式是至关重要的——如果你只使用缓存过滤器,它将在99.9999%的时间内工作。过早优化是万恶之源。谢谢你的建议!实际上,我并没有试图持久化docid。我将根据上面的示例代码持久化外部ID,在给定的时间点——在任何commit()或optimize()调用之间——我希望将外部ID转换为相应的docID,构建一个过滤器并使用它。我遇到的问题是,我没有从转换步骤中获得预期的结果。也许我没有使用正确的方法将外部ID转换为docID。@Gene Golovchinsky:我添加了一些代码,可能会有所帮助。正如我所说,你之前遇到的问题是Lucene的文档ID!=id字段的值,因此无法通过切换它们的值进行枚举。虽然下面Xodarap的答案远比上面我的代码好,但代码实际起了作用——问题是由于迭代调试,我有重复的外部id。下面Xodarap的答案远比上面我的代码好,代码实际上是有效的——问题是由于迭代调试,我有重复的外部ID。