【问题标题】:How to perform a lucene query containing special character using QueryParser?如何使用 QueryParser 执行包含特殊字符的 lucene 查询?
【发布时间】:2013-07-24 05:26:18
【问题描述】:

事情就是这样。我有一个存储在索引中的词,其中包含特殊字符,例如'-',最简单的代码是这样的:

Document doc = new Document();
doc.add(new TextField("message", "1111-2222-3333", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);

然后我使用 QueryParser 创建一个查询,如下所示:

String queryStr = "1111-2222-3333";
QueryParser parser = new QueryParser(Version.LUCENE_36, "message", new StandardAnalyzer(Version.LUCENE_36));
Query q = parser.parse(queryStr);

然后我使用搜索器搜索查询并没有得到任何结果。我也试过这个:

Query q = parser.parse(QueryParser.escape(queryStr));

仍然没有结果。

不使用 QueryParser 而是直接使用 TermQuery 可以做我想做的事,但是这种方式对于用户输入文本不够灵活。

我想也许 StandardAnalyzer 做了一些事情来省略查询字符串中的特殊字符。试了debug,发现字符串被拆分,实际查询是这样的:“message:1111 message:2222 message:3333”。不知道lucene到底做了什么……

所以如果我想用特殊字符执行查询,我应该怎么做?我应该重写分析器还是从默认的继承查询分析器?以及如何?...

更新:

1 @The New Idiot @femtoRgon,我已经尝试了问题中所述的 QueryParser.escape(queryStr),但它仍然不起作用。

2 我尝试了另一种解决问题的方法。我从Tokenizer派生了一个QueryTokenizer,只用空格截取单词,打包成一个QueryAnalyzer,派生自Analyzer,最后将QueryAnalyzer传递给QueryParser。

现在可以了。最初它不起作用,因为默认的 StandardAnalyzer 根据默认规则(将某些特殊字符识别为拆分器)切割 queryStr,当查询传递到 QueryParser 时,特殊字符已经被 StandardAnalyzer 删除。现在我使用我自己的方式来剪切 queryStr 并且它只将空格识别为分隔符,因此特殊字符保留在查询中等待处理并且这有效。

3 @The New Idiot @femtoRgon,感谢您回答我的问题。

【问题讨论】:

  • 抱歉,我显然没有仔细阅读。不过我很困惑:这个TextField 来自哪里? Lucene 的 TextField 不接受 Field.Index 参数(Field.Index 已弃用)。要创建与此处类似的字段,您可以使用StringField。这是某种自定义TextField 还是什么?
  • 对不起,这是我的错。我使用的是 Lucene 3.6,Lucene 3.x 中没有 TextField。正确的代码应该是:doc.add(new Field("message", "1111-2222-3333", Field.Store.YES, Field.Index.NOT_ANALYZED));Lucene 4.x 和 3.x 的 API 有很大的不同,我还在尝试理解 lucene 4.x 的 API。
  • 啊,更有意义。有点跑题了,但是如果您想了解 4.x 中的更改,您是否看过migration guide?它指出了主要变化,并提供了一些理由。
  • 哦,我没见过。稍后我会研究它,这将非常有帮助。非常感谢:)
  • @Yuanchao-tang WhitespaceAnalyzer 的表现与您的有何不同? I derived a QueryTokenizer from Tokenizer and cut the word only by space

标签: java lucene


【解决方案1】:

对此我不确定,但我想您需要使用 \ 转义 -。根据Lucene docs

“-”或禁止运算符排除在“-”符号后包含术语的文档。

再次,

Lucene 支持对属于查询语法一部分的特殊字符进行转义。当前列表特殊字符为

+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /

要转义这些字符,请在字符前使用 \。

还请记住,如果某些字符在 Java 中有特殊含义,则需要转义两次。

【讨论】:

  • 感谢您的回答,我已经找到了解决此问题的方法,请查看我的更新。
  • 不要忘记从Lucene 4.0开始“/”也是一个特殊字符(用于正则表达式)。
【解决方案2】:

您可以将值添加为 addValue() 而不是 add 或 addText。然后使用 KyewordAnalyzer 而不是 Standard Analyzer 在特殊字符中搜索。 要么 使用 addValue() 添加数据,并在 luke 中搜索数据时,将特殊字符替换为通配符搜索字符 (?)。我已经尝试了两种方法和工作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-19
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    相关资源
    最近更新 更多