Elasticsearch:如何将多个过滤器应用于相同的值?

时间:2017-11-12 16:55:38

标签: elasticsearch

很简单:当一个字段有多个值时,如何只获取我的过滤器应用于多值字段中的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”且颜色为“绿色”的票证?

提前感谢您的任何建议。

1 个答案:

答案 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"]
}

无法知道同一对象上的颜色和代码。 (原始来源也会被存储,以便在您提出请求时返回,但这不是您搜索时查询的数据。)

此处有两种可能的解决方案:denormalizationnested 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"}
         }
     }
}