lucene - 在 Lucene 文档中获取术语位置的正确方法是什么?
问题描述
这个问题中的示例以及我在网络上看到的其他一些示例使用postings
a 的方法TermVector
来获取术语位置。从链接问题的示例中复制粘贴:
IndexReader ir = obtainIndexReader();
Terms tv = ir.getTermVector( doc, field );
TermsEnum terms = tv.iterator();
PostingsEnum p = null;
while( terms.next() != null ) {
p = terms.postings( p, PostingsEnum.ALL );
while( p.nextDoc() != PostingsEnum.NO_MORE_DOCS ) {
int freq = p.freq();
for( int i = 0; i < freq; i++ ) {
int pos = p.nextPosition(); // Always returns -1!!!
BytesRef data = p.getPayload();
doStuff( freq, pos, data ); // Fails miserably, of course.
}
}
}
这段代码对我有用,但让我抓狂的是Terms
类型是保存位置信息的地方。我看到的所有文档都在说术语向量保留位置数据。但是,此类型没有获取该信息的方法!
较旧版本的 Lucene 显然有一种方法,但至少在 Lucene 的 6.5.1 版本中,情况并非如此。
相反,我应该使用postings
方法并遍历文档,但我已经知道要处理哪个文档!
API文档没有说明只返回当前文档(术语向量所属的那个)的帖子,但是当我运行它时,我只得到当前文档。
这是从术语向量中获取位置数据的正确且唯一的方法吗?为什么会有这么不直观的 API?是否有文件解释为什么以前的方法改变了这一点?
解决方案
不知道“对还是错”,但对于 6.6.3 版,这似乎可行。
private void run() throws Exception {
Directory directory = new RAMDirectory();
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(new StandardAnalyzer());
IndexWriter writer = new IndexWriter(directory, indexWriterConfig);
Document doc = new Document();
// Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES
FieldType type = new FieldType();
type.setStoreTermVectors(true);
type.setStoreTermVectorPositions(true);
type.setStoreTermVectorOffsets(true);
type.setIndexOptions(IndexOptions.DOCS);
Field fieldStore = new Field("tags", "foo bar and then some", type);
doc.add(fieldStore);
writer.addDocument(doc);
writer.close();
DirectoryReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
Term t = new Term("tags", "bar");
Query q = new TermQuery(t);
TopDocs results = searcher.search(q, 1);
for ( ScoreDoc scoreDoc: results.scoreDocs ) {
Fields termVs = reader.getTermVectors(scoreDoc.doc);
Terms f = termVs.terms("tags");
TermsEnum te = f.iterator();
PostingsEnum docsAndPosEnum = null;
BytesRef bytesRef;
while ( (bytesRef = te.next()) != null ) {
docsAndPosEnum = te.postings(docsAndPosEnum, PostingsEnum.ALL);
// for each term (iterator next) in this field (field)
// iterate over the docs (should only be one)
int nextDoc = docsAndPosEnum.nextDoc();
assert nextDoc != DocIdSetIterator.NO_MORE_DOCS;
final int fr = docsAndPosEnum.freq();
final int p = docsAndPosEnum.nextPosition();
final int o = docsAndPosEnum.startOffset();
System.out.println("p="+ p + ", o=" + o + ", l=" + bytesRef.length + ", f=" + fr + ", s=" + bytesRef.utf8ToString());
}
}
}
推荐阅读
- python - 如何从第二项迭代python dict
- java - 通过实现 onSeekBarChangeListener 在 TextView 中的多个搜索栏值
- angular - 错误 ReferenceError:particleJS 未定义 ~ Angular Universal + Webpack
- c# - ExpectedObjects 比较具体对象而不仅仅是接口
- python-3.x - RuntimeError:后端 CPU 的预期对象,但为参数 #2 'weight' 获得了后端 CUDA
- python-3.x - 尝试下载自制软件
- facebook - Firebase Facebook 身份验证:格式错误或过期的身份验证凭据
- php - 无法从会话设置电子邮件变量,因此 mail() 函数正常工作
- java - 如何使用 IF 条件比较 Flutter (dart) 中的两个 DateTime 值?
- amazon-web-services - 如何使用 terraform 向现有 EC2 实例添加新的安全规则