代码之家  ›  专栏  ›  技术社区  ›  Francesco Abeni

Elasticsearch:如何对同一个值应用多个过滤器?

  •  2
  • Francesco Abeni  · 技术社区  · 7 年前

    简而言之:当一个字段有多个值时,如何仅获取两个过滤器应用于多个值字段中相同值的项目?

    细节

    我在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 回复  |  直到 7 年前
        1
  •  1
  •   dshockley    7 年前

    您的问题是由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"}
             }
         }
    }