0

我正在使用 Lucene 3.6.1。我收到来自用户的查询。此查询可能包含+-运算符,也可能包含短语。在某些情况下,我想通过添加一些我计算的额外术语来扩展查询。这些条款是可选的。但是,必须遵守用户指定的任何必需的包含/排除约束。

我最初的策略是创建一个BooleanQuery,向其中添加一个包含已解析用户查询的子句,然后添加包含我的扩展术语的更多子句。扩展项将全部添加为Occur.SHOULD。我的问题是如何约束用户的查询。我可以想象三种可能性:

  1. 用户的查询不包含运算符,这意味着我可以将其作为Occur.SHOULD子句包含在内。

  2. 用户的查询包含一个+运算符,因此我需要将其作为Occur.MUST子句包含在内。

  3. 用户的查询包含一个-运算符,但也包含其他术语:我是否仍将其作为Occur.MUST子句包含在内?

这三个选择中隐含的问题是我如何判断哪个条件是合适的?我想我可以重写查询并测试BooleanQuery实例,但这似乎很脆弱。

我想也可以尝试从用户的输入和我的扩展术语中创建单个字符串的策略,如下所示:

(fld1:userterm1 userterm2 -fld2:userterm3 +userterm4)^10 (fld1:expterm1)^8 (fld2:expterm2)^7 ...

这是最好的方法吗?还是有一些优雅的编程解决方案?

4

1 回答 1

0

好的,不确定这个答案会有多大用处,但似乎无法在这里给出一个硬性和快速的答案,所以我将列出几个想到的可能性:

首先,一个问题:

将查询修改为如下所示:

(userquery) (other) (stuff)

我在您显示的规则中添加 + 是有道理的,但是“-”禁止的术语将很难正确遵守,因为(query -prohibition) (other)将允许与其他存在禁止的匹配,并且+(query -prohibition) (other)需要匹配“查询” .

我认为真正做到这一点的唯一方法是将禁止的术语也传播到您自动添加的术语中,或者将其提取到父查询层,更像(query -prohibition)--> (query) (other) -(prohibition)

并且随着用户输入任意复杂的查询,这可能不是一个好策略。


如果您想通过修改查询字符串来解决它,那么您可能应该在查询末尾添加任何术语。仅此而已。

我不相信

(fld1:userterm1 userterm2 -fld2:userterm3 +userterm4)^10 (fld1:expterm1)^8 (fld2:expterm2)^7 ...

令人满意,因为 userterm4 仅在其子查询中是必需的,但仅在 expterm1 上的匹配仍然是可以接受的。但是,像这样的查询:

fld1:userterm1 userterm2 -fld2:userterm3 +userterm4 (fld1:expterm1)^.8 (fld2:expterm2)^.7 ...

我认为,应该满足您的需求,并让您不必担心查询解析器的内部结构。 我认为这是最好的方法。


我还可以在结构如下的查询中看到逻辑

+(parsed userquery) (other stuff)

实际上,始终要求用户查询匹配。从某种意义上说,Lucene 隐含地这样做了,因为它不会返回与任何术语不匹配的结果,即使查询中不存在必填字段。然后,这将使用您添加的术语来影响评分,而不是返回更大的文档集。这并不能完全解决您的要求,但可能值得考虑。


如果尽管存在上述应用它们的问题,但您仍想检测“+”和“-”运算符,我认为可以合理地假设 StandardQueryParser 将为您需要检查的任何查询返回基本级别的 BooleanQuery这些操作数。例如,您可能不得不担心 DisjunctionMaxQueries,以及当您使用运算符进行简单查询时会发生什么,例如:

+myterm

我不知道 QueryParser 是否会简单地返回一个 TermQuery,从而失去加号(因为如果没有另一个术语存在,它将是多余的)。像这样的担忧让我犹豫以这种方式解决它。

同样,尝试从查询字符串中检测这些值必须对事物的解析方式做出假设,并且可能会变得复杂。


总结一下,我认为最好的选择是:在进行任何解析之前将术语添加到原始查询字符串的末尾,或者将用户查询视为原子,并在添加到布尔值时定义独立于其内容的适当布尔子句子句用您需要包含的任何其他查询来包装它。

于 2012-12-06T06:59:45.277 回答