我试图用Java生成查询来搜索Lucene索引。有问题的记录有一个recordState字段,所以我用以下内容开始查询:
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(new TermQuery(new Term("recordState", "DRAFT")), Occur.MUST);
当我想添加用户提供的过滤器时,会出现问题。我曾尝试将代码更改为:
String userQuery = ""; // This will be whatever the user types in
QueryParser queryParser = new QueryParser(Version.LUCENE_29, "", new StandardAnalyzer(Version.LUCENE_29,
new HashSet<String>()));
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(new TermQuery(new Term("recordState", "DRAFT")), Occur.MUST);
booleanQuery.add(queryParser.parse(userQuery), Occur.MUST);
如果用户输入record_id:123
作为查询,我最终得到的查询将为+recordState:DRAFT +record_id:123
- 很棒。如果用户输入+record_id:123
,则最终查询为+recordState:DRAFT +(+record_id:123)
- 不理想但可行。
但是,如果用户输入-record_id:123
,则最终查询为+recordState:DRAFT +(-record_id:123)
,看起来无效&amp;没有多大意义!
有没有更好的方法来组合两个查询部分?我无法将用户的查询作为纯文本附加,就好像他们不会以+/-开头,查询最终会为+recordState:DRAFT record_id:123
(记录状态=草稿或记录ID)。
我认为我唯一能做的就是测试用户查询是否只包含一个术语&amp;如果是这样,删除任何前面的+/-。但我想这样做没有任何字符串操作&amp;坚持使用Lucene API。
答案 0 :(得分:2)
实际上,您提供的语法并不是那么严重,但可能并不像您期望的那样。
查询:
-record_id:123
不是很有用。 Lucene不支持纯负面查询。 Lucene需要搜索一些东西,如果只有不匹配,它就不会匹配。
由于您的目标似乎只是过滤到只有recordState
= DRAFT
的文档,并且已经获得了有效查询,因此用户输入的查询结果是不合理的。真的没什么好处。
如下的查询:
+recordState:DRAFT +(-record_id:123 anotherfield:terms)
会很好,并且:
+recordState:DRAFT +(+record_id:123)
括号内的+
并不是必需的,但它也可以毫无问题地工作。
如果要通过分析查询字符串或从解析器迭代BooleanQuery
返回来检测这样的纯否定查询,请执行以下操作:
BooleanQuery query = (BooleanQuery)parser.parse;
BooleanClause[] clauses = query.getClauses();
if (clauses.length == 1 && clauses[0].getOccur() == BooleanClause.Occur.MUST_NOT) {
booleanQuery.add(clauses[0]);
} else {
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
这可能会处理非常具体的情况,但请记住,如果用户可以创建任意复杂性的查询,他们也可以创建嵌套在查询中某处的相同问题。此外,不保证查询解析器返回BooleanQuery
,因此这是一个假设。