3

我试图弄清楚有效载荷在 Lucene 中的工作方式,但我似乎无法掌握它。我的情况如下:

我需要索引一个具有单个内容字段的文档,并从该字段中的文本中为每个令牌附加一个有效负载(大约 10 个字节)。我需要使用的分析器是一个基本的空白分析器。

从我在互联网上阅读的各种文章来看,使用有效负载的方法是创建我自己的分析器并在标记化步骤中附加有效负载。我为我的新自定义分析器提供了以下代码:

public TokenStream tokenStream(String fieldName, Reader reader) {
    TokenStream tokenStream = new WhitespaceTokenizer(Version.LUCENE_31,
            reader);

    OffsetAttribute offsetAttribute = tokenStream
            .getAttribute(OffsetAttribute.class);
    CharTermAttribute termAttribute = tokenStream
            .getAttribute(CharTermAttribute.class);
    if (!tokenStream.hasAttribute(PayloadAttribute.class)) {
        tokenStream.addAttribute(PayloadAttribute.class);
    }
    PayloadAttribute payloadAttribute = tokenStream
            .getAttribute(PayloadAttribute.class);

    try {
        while (tokenStream.incrementToken()) {
            int startOffset = offsetAttribute.startOffset();
            int endOffset = offsetAttribute.endOffset();

            String token;

            try{
                token = (termAttribute.subSequence(startOffset, endOffset)).toString();
            }
            catch(IndexOutOfBoundsException ex){
                token = new String(termAttribute.buffer());
            }

            byte[] payloadBytes = payloadGenerator.generatePayload(token,
                    frequencyClassDigest);
            payloadAttribute.setPayload(new Payload(payloadBytes));
        }
        tokenStream.reset();

        return tokenStream;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

我遇到的问题如下:

  1. 我无法正确读取各个令牌。我不确定使用 CharTermAttribute 是不是正确的方法,但我知道它不起作用。我需要获取单个令牌才能正确计算有效负载,但是 WithespaceTokenizer 以某种方式返回粘合在一起的单个单词(一次 3 个单词)。
  2. 我不知道使用 PayloadAttribute 是否是将有效负载附加到令牌的正确方法。也许你知道另一种方式

我在哪里可以找到一些关于如何在 Lucene 中实际使用 Payload 的好教程?我试过在网上搜索,我能找到的唯一一篇好文章是:Lucene Payload tutorial但是它并不完全适合我的需要。

谢谢

好像找不到好的教程

4

1 回答 1

2

您可以将有效负载生成逻辑封装在过滤器中,该过滤器将为通过过滤器的每个令牌生成有效负载。我已经根据 Lucene 的DelimitedPayloadTokenFilter.

public final class PayloadGeneratorFilter extends TokenFilter {
  private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
  private final PayloadAttribute payAtt = addAttribute(PayloadAttribute.class);
  private final PayloadGenerator payloadGenerator;
  private final FrequencyClassDigest frequencyClassDigest;


  public PayloadGeneratorFilter(TokenStream input, PayloadGenerator payloadGenerator,
                                FrequencyClassDigest frequencyClassDigest) {
    super(input);
    this.payloadGenerator = payloadGenerator;
    this.frequencyClassDigest = frequencyClassDigest;
  }

  @Override
  public boolean incrementToken() throws IOException {
    if (input.incrementToken()) {
      final char[] buffer = termAtt.buffer();
      final int length = termAtt.length();
      String token = buffer.toString();
      byte[] payloadBytes = payloadGenerator.generatePayload(token, frequencyClassDigest);
      payAtt.setPayload(new Payload(payloadBytes));
      return true;
    }

    return false;
  }
}

这将使您的分析器代码非常简单:

public class NLPPayloadAnalyzer extends Analyzer {
  private PayloadGenerator payloadGenerator;
  private FrequencyClassDigest frequencyClassDigest;

  public NLPPayloadAnalyzer(PayloadGenerator payloadGenerator,
                            FrequencyClassDigest frequencyClassDigest) {
    this.payloadGenerator = payloadGenerator;
    this.frequencyClassDigest = frequencyClassDigest;
  }

  public TokenStream tokenStream(String fieldName, Reader reader) {
    TokenStream tokenStream = new WhitespaceTokenizer(Version.LUCENE_31, reader);
    tokenStream = new PayloadGeneratorFilter(tokenStream, payloadGenerator, frequencyClassDigest);
    return tokenStream;
  }
}

另一种方法是预处理您的有效负载并将它们附加到您发送到 Lucene 的文本中,然后使用DelimitedPayloadTokenFilter. text text text text 会成为 text|1.0 text|2.2 text|0.5 text|10.5

http://sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html也是一个很好的资源。

于 2011-08-10T21:28:11.053 回答