使用Lucene索引,我有一个标准的文档格式,如下所示:
Name: John Doe Job: Plumber Hobby: Fishing
我的目标是将有效负载附加到作业字段,该作业字段将包含有关管道的其他信息,例如,管道文章的维基百科链接。我不想把有效载荷放在其他地方。最初,我找到了一个涵盖我想做的事情的例子,但是它使用了Lucene 2.2,并且没有更新来反映令牌流api中的变化。 经过一些更多的研究,我想出了这个小怪物来为该领域构建自定义令牌流。
public static TokenStream tokenStream(final String fieldName, Reader reader, Analyzer analyzer, final String item) {
final TokenStream ts = analyzer.tokenStream(fieldName, reader) ;
TokenStream res = new TokenStream() {
CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
PayloadAttribute payAtt = addAttribute(PayloadAttribute.class);
public boolean incrementToken() throws IOException {
while(true) {
boolean hasNext = ts.incrementToken();
if(hasNext) {
termAtt.append("test");
payAtt.setPayload(new Payload(item.getBytes()));
}
return hasNext;
}
}
};
return res;
}
当我获取令牌流并迭代所有结果时,在将其添加到字段之前,我看到它成功配对了术语和有效负载。在流上调用reset()之后,我将它添加到文档字段并索引文档。但是,当我打印出文档并使用Luke查看索引时,我的自定义令牌流没有进行剪切。字段名称正确显示,但标量流中的术语值不会出现,也不表示有效负载的成功附加。
这引出了两个问题。首先,我是否正确使用了令牌流,如果是这样,当我将其添加到字段时,为什么不进行令牌化?其次,如果我没有正确使用流,我是否需要编写自己的分析器。使用Lucene标准分析器将此示例拼凑在一起以生成令牌流并写入文档。如果可能的话,我想避免编写自己的分析器,因为我只希望将有效负载附加到一个字段!
编辑:
致电代码
TokenStream ts = tokenStream("field", new StringReader("value"), a, docValue);
CharTermAttribute cta = ts.getAttribute(CharTermAttribute.class);
PayloadAttribute payload = ts.getAttribute(PayloadAttribute.class);
while(ts.incrementToken()) {
System.out.println("Term = " + cta.toString());
System.out.println("Payload = " + new String(payload.getPayload().getData()));
}
ts.reset();
答案 0 :(得分:1)
很难说出为什么没有保存有效负载,原因可能在于使用您提供的方法的代码。
设置有效负载的最便捷方式是TokenFilter
- 我认为采用这种方法可以为您提供更清晰的代码,从而使您的方案正常运行。我认为在Lucene源中查看这种类型的过滤器是最具说明性的,例如: TokenOffsetPayloadTokenFilter
。您可以在test for this class中找到如何使用它的示例。
还请考虑是否没有更好的地方来存储这些超链接而不是有效负载。有效载荷具有非常特殊的应用,例如提升一些术语取决于它们在原始文档中的位置或格式,词性......它们的主要目的是影响搜索的执行方式,因此它们通常是数值,有效地打包以减少索引大小。
答案 1 :(得分:0)
我可能会遗漏一些东西,但...... 您不需要自定义标记生成器将其他信息与Lucene文档相关联。只是商店是一个未经分析的领域。
doc.Add(new Field("fname", "Joe", Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("job", "Plumber", Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("link","http://www.example.com", Field.Store.YES, Field.Index.NO));
然后,您可以像任何其他字段一样获取“链接”字段。
此外,如果你确实需要一个自定义标记器,那么你肯定需要一个自定义分析器来实现它,用于索引构建和搜索。