从用户输入创建查询&已知领域

时间:2014-04-02 15:33:17

标签: java lucene

我试图用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。

1 个答案:

答案 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,因此这是一个假设。