如何构建一个类似于此的json Elasticsearch查询(英文):
foo WITHIN 1 (biz AND buz)
我希望查询返回biz
和buz
都存在的文档,以及单词foo
与其中一个单词相邻的文档。
例如,以下文档应匹配:
以下文档应不匹配:
我的原始解决方案
我的第一个想法是使用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
(对于我的域名实际上是无限的)。很遗憾,上述查询无效。相反,上述查询会返回包含1000000
,foo
和biz
字样的所有文档,并且buz
出现在foo
和biz
之间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
。它需要两个运算符include
和exclude
,并且有效地与a AND NOT b
类似。跨度没有match_all
,因此您不能简单地将a
设置为所有内容。
注意:我正在使用Elasticsearch,但这个问题同样适用于Lucene使用他们的Java原语。