在这个问题上,假设我们有一个
这样的映射{
tags: { type: 'string' }, // array of strings input
name: { type: 'string' }
}
给标签一个数组。假设我们随后将以下文档编入索引:
[{
tags: ['a', 'b', 'c'],
name: 'Alpha'
}, {
tags: ['b', 'c', 'd'],
name: 'Beta'
}, {
tags: ['c', 'd', 'e'],
name: 'Gamma'
}, {
tags: ['b', 'c', 'd', 'e'],
name: 'Delta'
}, {
tags: [],
name: 'Eta'
}]
有没有一种结构化查询的方法,使得它可以找到给定数组中具有至少一个标签 not 的所有文档?例如,给出['b','c','d'] ,它应返回名为 Alpha
的对象(不包含'a'在给定数组中), Gamma
(在给定数组中没有'e')和 Delta
(也有'e'不在给定数组中。)
答案 0 :(得分:0)
如果您可以将“输入数组”的概念更改为布尔查询-这将起作用
{
"query": {
"bool": {
"should": [
{
"bool": {
"must_not": {
"term": {
"tags": "b"
}
}
}
},
{
"bool": {
"must_not": {
"term": {
"tags": "c"
}
}
}
},
{
"bool": {
"must_not": {
"term": {
"tags": "d"
}
}
}
}
],
"must" : { "wildcard" : {"tags": "*"}},
"minimum_should_match": 1
}
}
}
答案 1 :(得分:0)
恐怕这是不可能的,因为Elasticsearch将数据存储在inverted indexes中,该数据结构可以回答“哪些文档具有特定标记”而不是“哪些文档没有其他标记”的问题“。
您可以尝试几种方法。
tags
如果事先知道所有可能的tags
的集合,并且字段的基数(==唯一标记的数量)不太高(例如,小于1000),则可以这样做。 / p>
如果可能值的集合未知,则可以通过terms
聚合来获取。在这种情况下,您将必须执行2个查询,而不是1个。
在您所提问题的示例中,这意味着要索取在["a", "e"]
中带有标签的所有文档。
script
查询 script
查询本质上是full-scan查询,并允许用户根据需要定义匹配/不匹配条件。主要缺点是性能,因为Elasticsearch将无法使用其任何反向索引,因此本质上将必须扫描所有文档。
此选项在某些情况下可能会有用,例如进行分析或证明某些假设。
由于通用方法不可行,因此可能会证明您的业务案例实际上不是通用的。查看您需要执行的查询,并针对用例进行优化。
例如,如果搜索“任何但 b,c,d 的标签”是重复的用例,则定义一个类似标志的字段"contains_not_b_c_d"
并预先计算。
我真的希望我能对此做出更积极的评价,但这种用例并不是Elasticsearch兴旺发达的地方。
希望有帮助!