Lucene的3.5自定义有效载荷

问题描述:

与Lucene索引工作,我有一个标准的文档格式,看起来是这样的:Lucene的3.5自定义有效载荷

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查看索引时,我的自定义标记流没有完成剪切。字段名称显示正确,但来自标记流的术语值不会显示,也不会显示成功附加有效内容。

这使我2个问题。首先,我是否正确使用了令牌流,如果是的话,为什么它不会在我将其添加到域时进行标记?其次,如果我没有正确使用流,是否需要编写我自己的分析器。这个例子使用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(); 

这是很难说为什么有效载荷不会被保存,其原因可能在使用您所提出的方法的代码所在。

最方便的方式来设置有效载荷是在TokenFilter - 我认为,采用这种方法会给你更清洁的代码,进而正确地使您的方案工作。我认为在Lucene源代码中查看一些这种类型的过滤器是最具说明性的,例如, TokenOffsetPayloadTokenFilter。您可以在test for this class中找到应该如何使用它的示例。

也请考虑一下,如果没有更好的地方来存储这些超链接比在有效载荷。有效载荷对于例如提高取决于他们的位置或原始文档的格式的一些术语,词性......他们的主要目的是为了影响如何执行搜索,所以它们通常数值,有效的填充,以减少索引大小。

+0

我会在今天晚些时候更新调用代码的帖子。最终的数据可能不是超链接,我试图让这个概念起作用,并且超链接是我组装示例时首先想到的第一件事。 :) – FloppyDisk 2012-02-10 18:24:59

+0

您是否研究过我建议的解决方案,即实施'TokenFilter'?它肯定会使代码更加清洁,并且是在Lucene中执行此类事情的最自然的方式。 – 2012-02-11 16:39:45

+0

对不起,延迟了,我看过了。如果我可以避免,我想避免暂时编写我自己的分析仪。但是,看起来这就是我所要做的。 – FloppyDisk 2012-02-13 14:21:46

我可能失去了一些东西,但是...... 你不需要自定义标记生成附加信息的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)); 

然后,您可以像任何其他字段一样获取“链接”字段。

另外,如果你确实需要一个自定义的标记生成器,那么你肯定会需要一个定制的分析来实现它,同时为建立索引和搜索。

+0

我搞砸了,问题是,速度很慢。我无法利用“发布”列表来检索一条信息。相反,我必须击中每个文档,从索引中加载文档,然后获取该字段。花费太多时间。 – FloppyDisk 2012-02-10 18:24:06