【问题标题】:QueryParser with CustomAnalyzer messes order of use of PatternReplaceCharFilter带有 CustomAnalyzer 的 QueryParser 混淆了 PatternReplaceCharFilter 的使用顺序
【发布时间】:2016-08-22 23:19:43
【问题描述】:

我在 lucene 6.0.0 中使用org.apache.lucene.queryparser.classic.QueryParser 来解析使用CustomAnalyzer 的查询,如下所示:

public static void testFilmAnalyzer() throws IOException, ParseException {
    CustomAnalyzer nameAnalyzer = CustomAnalyzer.builder()
            .addCharFilter("patternreplace",
                    "pattern", "(movie|film|picture).*",
                    "replacement", "")
            .withTokenizer("standard")
            .build();

    QueryParser qp = new QueryParser("name", nameAnalyzer);
    qp.setDefaultOperator(QueryParser.Operator.AND);
    String[] strs = {"avatar film fiction", "avatar-film fiction", "avatar-film-fiction"};

    for (String str : strs) {
        System.out.println("Analyzing \"" + str + "\":");
        showTokens(str, nameAnalyzer);
        Query q = qp.parse(str);
        System.out.println("Parsed query of \"" + str + "\":");
        System.out.println(q + "\n");
    }
}

private static void showTokens(String text, Analyzer analyzer) throws IOException {
    StringReader reader = new StringReader(text);
    TokenStream stream = analyzer.tokenStream("name", reader);
    CharTermAttribute term = stream.addAttribute(CharTermAttribute.class);
    stream.reset();
    while (stream.incrementToken()) {
        System.out.print("[" + term.toString() + "]");
    }
    stream.close();
    System.out.println();
}

当我调用 testFilmAnalyzer 时,我得到以下输出:

Analyzing "avatar film fiction":
[avatar]
Parsed query of "avatar film fiction":
+name:avatar +name:fiction

Analyzing "avatar-film fiction":
[avatar]
Parsed query of "avatar-film fiction":
+name:avatar +name:fiction

Analyzing "avatar-film-fiction":
[avatar]
Parsed query of "avatar-film-fiction":
name:avatar

分析器似乎以正确的预期顺序使用PatternReplaceCharFilter(即在标记化之前),而QueryParser 在之后使用。有人对此有解释吗?这不是bug吗?

【问题讨论】:

    标签: java lucene query-parser


    【解决方案1】:

    不,这不是错误。 CharFilters总是在标记化之前应用,无论是在查询时还是索引时。

    然而,空格在QueryParser语法中是有意义的,完全独立于分析。将查询的单独子句分隔开来,并且每个子句都单独进行分析。如果您不依赖默认字段,这更容易看出,在这种情况下,我们需要将查询:avatar-film fiction 重写为:name:avatar-film name:fiction。 “avatar-film”和“fiction”这两个子句中的每一个都分别进行分析,从而导致您看到的结果。

    尝试使用短语查询:

    String[] strs = {"\"avatar film fiction\"", "\"avatar-film fiction\"", "\"avatar-film-fiction\""};
    

    您应该会看到预期的结果。

    【讨论】:

      猜你喜欢
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 2011-12-01
      • 2012-02-18
      相关资源
      最近更新 更多