【问题标题】:Lucene QueryParser vs. TermQueryLucene QueryParser 与 TermQuery
【发布时间】:2014-02-28 16:31:24
【问题描述】:

我目前不确定 Lucene 中 QueryParser 与 TermQuery 的行为;我正在使用 Lucene 3.6。

在我的示例中,我在同一索引上尝试以下示例,其中相关字段设置为 Field.Store.NOField.Index.NOT_ANALYZED_NO_NORMS

Query q1 = new TermQuery(new Term("names", "test three"));

QueryParser q2p = new QueryParser(GenericIndexer.LUCENE_VERSION, "names", someAnalyzer);
Query q2 = q2p.parse("names:test three");
Query q3 = q2p.parse("names:\"test three\"");

q2q3 这两种情况下,我都无法重现与q1 相同的语法;通过打印查询,我可以看到:

  • q1 = names:test three
  • q2 = names:test names:three
  • q3 = names:"test three"

由于这种差异,查询 q2q3 不返回任何结果,而查询 q1 返回预期结果。

问题:有没有办法让查询解析器重现与 TermQuery 相同的查询,或者我在这里遗漏了一些基本的 Lucene 概念?

注意:对于 QueryParser,分析器与索引期间使用的分析器相同,尽管我不确定这些信息的相关性。

【问题讨论】:

    标签: java search lucene


    【解决方案1】:

    使用您的TermQuery,您将生成一个术语test three。由于没有分析该字段,因此产生一个术语是正确的。

    在 q2 中,由于查询解析器的语法,您会看到两个单独的术语。真正在做的是与查询类似; names:test defaultField:three,虽然这并不明显,因为您的默认字段也是“名称”

    在 q3 中(您注意到的地方确实非常相关!),您生成了一个短语查询,它与您在 q1 中提供的 TermQuery 不太一样,但使用正确的分析器,它可以等价。 PhraseQueries 被分析,我猜查询解析器使用的分析器是StandardAnalyzer,或者类似的东西。不同之处在于术语的外观:

    • StandardAnalyzer 分析的术语:test - three
    • 未分析字段中的术语:test three

    因此,两种表示之间没有相同的术语可以匹配。相反,请尝试使用KeywordAnalyzer,这实际上与使用未分析的字段相同。

    您通常希望确保在 QueryParser 中使用与分析文档相同的分析器,KeywordAnalyzer 是未分析字段事实上的等效分析器。

    【讨论】:

    • 谢谢,我尝试使用以下代码,通过引号传递查询:QueryParser qp = new QueryParser(GenericIndexer.LUCENE_VERSION, "names", new KeywordAnalyzer()); Query qq = qp.parse("\"test three\""); 并得到了预期的结果。我有点担心对特定字段使用不同的分析器,您是否建议对索引为 NOT_ANALYZED_NO_NORMS 的字段坚持使用术语查询?
    • 对不同的领域使用不​​同的分析器是相当标准的,并且得到很好的支持(看看PerFieldAnalyzerWrapper)。构造一个TermQuery,我发现这是处理未分析字段的最简单方法,其他条件相同。但是,如果我需要支持跨已分析和未分析字段的已解析查询,我会将PerFieldAnalyzerWrapper 传递给 QueryParser。以适合您和情况的为准。
    • @Luca - 在被队列拒绝之前没有看到您的编辑(当您在编辑队列中遇到类似的编辑时,很难弄清楚它背后的原因)。我已经着手进行了更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 2010-09-20
    • 2013-02-20
    • 2014-08-07
    相关资源
    最近更新 更多