39

有没有一种简单的方法可以使用 Lucene 的任何子类Analyzer来解析/标记 a String

就像是:

String to_be_parsed = "car window seven";
Analyzer analyzer = new StandardAnalyzer(...);
List<String> tokenized_string = analyzer.analyze(to_be_parsed);
4

4 回答 4

57

根据上面的答案,这稍作修改以与 Lucene 4.0 一起使用。

public final class LuceneUtil {

  private LuceneUtil() {}

  public static List<String> tokenizeString(Analyzer analyzer, String string) {
    List<String> result = new ArrayList<String>();
    try {
      TokenStream stream  = analyzer.tokenStream(null, new StringReader(string));
      stream.reset();
      while (stream.incrementToken()) {
        result.add(stream.getAttribute(CharTermAttribute.class).toString());
      }
    } catch (IOException e) {
      // not thrown b/c we're using a string reader...
      throw new RuntimeException(e);
    }
    return result;
  }

}
于 2012-03-05T07:03:45.117 回答
40

据我所知,您必须自己编写循环。像这样的东西(直接取自我的源代码树):

public final class LuceneUtils {

    public static List<String> parseKeywords(Analyzer analyzer, String field, String keywords) {

        List<String> result = new ArrayList<String>();
        TokenStream stream  = analyzer.tokenStream(field, new StringReader(keywords));

        try {
            while(stream.incrementToken()) {
                result.add(stream.getAttribute(TermAttribute.class).term());
            }
        }
        catch(IOException e) {
            // not thrown b/c we're using a string reader...
        }

        return result;
    }  
}
于 2011-06-13T19:11:46.797 回答
2

使用 try-with-resources 会更好!这样您就不必显式调用.close()更高版本的库中所需的内容。

public static List<String> tokenizeString(Analyzer analyzer, String string) {
  List<String> tokens = new ArrayList<>();
  try (TokenStream tokenStream  = analyzer.tokenStream(null, new StringReader(string))) {
    tokenStream.reset();  // required
    while (tokenStream.incrementToken()) {
      tokens.add(tokenStream.getAttribute(CharTermAttribute.class).toString());
    }
  } catch (IOException e) {
    new RuntimeException(e);  // Shouldn't happen...
  }
  return tokens;
}

和 Tokenizer 版本:

  try (Tokenizer standardTokenizer = new HMMChineseTokenizer()) {
    standardTokenizer.setReader(new StringReader("我说汉语说得很好"));
    standardTokenizer.reset();
    while(standardTokenizer.incrementToken()) {
      standardTokenizer.getAttribute(CharTermAttribute.class).toString());
    }
  } catch (IOException e) {
      new RuntimeException(e);  // Shouldn't happen...
  }
于 2019-02-07T17:40:17.310 回答
1

正如另一个 Stack Overflow 答案所表明的那样,最新的最佳实践似乎是向令牌流添加一个属性,然后再访问该属性,而不是直接从令牌流中获取一个属性。为了更好地衡量,您可以确保分析仪关闭。使用最新的 Lucene(当前为 v8.6.2),代码如下所示:

String text = "foo bar";
String fieldName = "myField";
List<String> tokens = new ArrayList();
try (Analyzer analyzer = new StandardAnalyzer()) {
  try (final TokenStream tokenStream = analyzer.tokenStream(fieldName, text)) {
    CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
    tokenStream.reset();
    while(tokenStream.incrementToken()) {
      tokens.add(charTermAttribute.toString());
    }
    tokenStream.end();
  }
}

该代码完成后,tokens将包含已解析标记的列表。

另请参阅:Lucene 分析概述

警告:我刚刚开始编写 Lucene 代码,所以我没有很多 Lucene 经验。但是,我花时间研究了最新的文档和相关帖子,并且我相信我在这里放置的代码遵循最新推荐的做法,比当前的答案要好一些。

于 2020-09-20T19:05:26.583 回答