Java 如何使用QueryParser执行包含特殊字符的lucene查询?

Java 如何使用QueryParser执行包含特殊字符的lucene查询?,java,lucene,Java,Lucene,事情是这样的。索引中存储了一个术语,它包含特殊字符,如“-”,最简单的代码如下: Document doc = new Document(); doc.add(new TextField("message", "1111-2222-3333", Field.Store.YES, Field.Index.NOT_ANALYZED)); writer.addDocument(doc); String queryStr = "1111-2222-3333"; QueryParser parser =

事情是这样的。索引中存储了一个术语,它包含特殊字符,如“-”,最简单的代码如下:

Document doc = new Document();
doc.add(new TextField("message", "1111-2222-3333", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
String queryStr = "1111-2222-3333";
QueryParser parser = new QueryParser(Version.LUCENE_36, "message", new StandardAnalyzer(Version.LUCENE_36));
Query q = parser.parse(queryStr);
然后我使用QueryParser创建了一个查询,如下所示:

Document doc = new Document();
doc.add(new TextField("message", "1111-2222-3333", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
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做了一些事情来省略查询字符串中的特殊字符。我尝试调试,发现字符串被拆分,实际查询如下:“message:1111 message:2222 message:3333”。我不知道lucene到底做了什么

因此,如果我想使用特殊字符执行查询,我应该怎么做?我应该重写分析器还是从默认分析器继承queryparser?怎么做

更新:

1@thenewidiot@femtoRgon,我已经尝试了问题中提到的QueryParser.escape(queryStr),但仍然不起作用

我试过另一种方法来解决这个问题。我从Tokenizer派生出一个QueryTokenizer,只按空格剪切单词,将其打包到一个QueryAnalyzer中,该QueryAnalyzer派生自Analyzer,最后将QueryAnalyzer传递到QueryParser中

现在它起作用了。最初它不起作用,因为默认的StandardAnalyzer根据默认规则(将一些特殊字符识别为拆分器)剪切queryStr,当查询传递到QueryParser时,特殊字符已经被StandardAnalyzer删除。现在我用我自己的方法剪切queryStr,它只将空格识别为拆分器,所以特殊字符保留在查询中等待处理,这就行了


3@thenewidoot@femtoRgon,谢谢你回答我的问题。

我不确定这一点,但我想你需要用
\
逃离
-
。按照

“-”或“禁止”运算符不包括包含“-”符号后的术语的文档

再说一遍

Lucene支持转义作为查询语法一部分的特殊字符。当前列表中的特殊字符为

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

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

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


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

感谢您的回答,我找到了解决此问题的方法,请参阅我的更新。不要忘记,从Lucene 4.0开始“/”也是一个特殊字符(在regex中使用)抱歉,我显然读得不够仔细。但是我很困惑:这个
TextField
来自哪里?Lucene的
TextField
没有使用
Field.Index
参数(
Field.Index
已弃用)。若要创建一个类似于此处的字段,您应该使用
StringField
。这是某种自定义
TextField
还是什么?对不起,这是我的错。我使用的是Lucene 3.6,Lucene 3.x中没有TextField。正确的代码应该是:
doc.add(新字段(“消息”,“1111-2222-3333”)“,Field.Store.YES,Field.Index.NOT_分析”)Lucene 4.x和3.x API非常不同,我仍在努力理解Lucene 4.x API。啊,这更有意义。有点离题了,但是如果你想了解4.x中的变化,你有没有看一下?它指出了主要的变化,并提供了一些基本原理。哦,我还没有看到。我稍后会研究,这将非常有帮助。非常感谢:)@Yuanchao tang WhitespaceAnalyzer的性能与您的有什么不同<代码>我从标记器派生了一个QueryTokenizer,并只按空格剪切单词