很简单:当一个字段有多个值时,如何只获取我的过滤器应用于多值字段中的SAME值的那些项目?
我在Elasticsearch中存储了一些具有多个值的嵌套字段的项目,例如
"hits": [
{
"name": "John",
"tickets": [
{
"color": "green",
"code": "001"
},
{
"color": "red",
"code": "002"
}
]
},
{
"name": "Frank",
"tickets": [
{
"color": "red",
"code": "001"
},
{
"color": "green",
"code": "002"
}
]
}
]
现在考虑这些过滤器:
...
filter: [
{ terms: { 'tickets.code': '001' } },
{ terms: { 'tickets.color': 'green' } },
]
...
两个项目都匹配,因为它们中的每一个都至少有一个代码为“001”的票证,并且每个票证都带有颜色为“绿色”的票证。
如何编写我的过滤器以便只有第一个匹配,因为它有一个代码为“001”且颜色为“绿色”的票证?
提前感谢您的任何建议。
答案 0 :(得分:1)
您的问题是由Elasticsearch flattens objects引起的。所以在内部,您的数据表示如下:
{
"name": "John",
"tickets.color": ["green", "red"],
"tickets.code": ["001", "002"]
},
{
"name": "Frank",
"tickets.color": ["red", "green"],
"tickets.code": ["001", "002"]
}
无法知道同一对象上的颜色和代码。 (原始来源也会被存储,以便在您提出请求时返回,但这不是您搜索时查询的数据。)
此处有两种可能的解决方案:denormalization或nested data type。如果你能完全摆脱它,那么非规范化是更好的选择,因为它更有效率。如果您对数据进行非规范化处理,最终可能会得到如下表示:
{
"name": "John",
"ticket": {
"color": "green",
"code": "001"
}
},
{
"name": "John",
"ticket": {
"color": "red",
"code": "002"
}
},
{
"name": "Frank",
"ticket": {
"color": "red",
"code": "001"
}
},
{
"name": , "Frank",
"ticket": {
"color": "green",
"code": "002"
}
}
如果使用嵌套数据类型,则必须使用如下映射:
{
"ticket": {
"type": "nested",
"properties": {
"color": {"type": "keyword"},
"code": {"type": "keyword"}
}
}
}