Elasticsearch:span_near,在span_near内有一个大斜率,有一个小斜率

时间:2014-10-16 03:50:45

标签: lucene elasticsearch

如何构建一个类似于此的json Elasticsearch查询(英文):

foo WITHIN 1 (biz AND buz)

我希望查询返回bizbuz都存在的文档,以及单词foo与其中一个单词相邻的文档。

例如,以下文档应匹配:

  • foo biz bar bar bar buz
  • bar bar foo biz bar buz

以下文档应匹配:

  • foo biz
  • foo bar biz buz
  • biz bar foo bar buz

我的原始解决方案

我的第一个想法是使用span_near,对于它的第一个子句,使用foo项,对于它的第二个子句,使用在{{1}上运行的布尔AND }和biz。但是,在Elasticsearch中,您不能在跨度内使用布尔值,您只能将其他跨度放在跨度内。此外,没有buz命令。因此,您必须使用具有大斜率的另一个span_and来模拟布尔AND

我尝试的解决方案是:

span_near

请注意,我们使用{'span_near': {'clauses': [{'span_term': {'text': 'foo'}}, {'span_near': {'clauses': [{'span_term': {'text': 'biz'}}, {'span_term': {'text': 'buz'}}], 'in_order': False, 'slop': 1000000}}], 'in_order': False, 'slop': 0}} 的slop模拟AND(对于我的域名实际上是无限的)。很遗憾,上述查询无效。相反,上述查询会返回包含1000000foobiz字样的所有文档,并且buz出现在foobiz之间buz


另一种解决方案,但是<< Onerous

另一种解决方案是将原始查询转换为:

(biz AND buz) AND ((foo WITHIN 1 biz) OR (foo WITHIN 1 buz))

这似乎很难实现,因为需要在AND操作中解析span_near个关键字并进行必要的转换。


另一种解决方案,不那么慷慨,但非常丑陋

另一种解决方案是返回到CS 101并利用De Morgan's law并使用span_not查询来有效地进行以下操作:

foo WITHIN 1 NOT (NOT biz OR NOT buz)

更新:第二种解决方案也不起作用。 span_not查询不是真正的NOT。它需要两个运算符includeexclude,并且有效地与a AND NOT b类似。跨度没有match_all,因此您不能简单地将a设置为所有内容。

注意:我正在使用Elasticsearch,但这个问题同样适用于Lucene使用他们的Java原语。

0 个答案:

没有答案