使用 Elasticsearch 从嵌套对象中过滤多个字段

Filtering on multiple fields from nested object with Elasticsearch

我是 Elasticsearch 的新手,我正在尝试编写一些查询,但碰巧不起作用。我有关于人的信息,我想根据一些属性查询人。

这是 Elasticsearch 中映射的一部分:

"properties": {
    "doc": {
        ...
        "languages": [{
                "language": {
                    "type": "text",
                    "null_value": "NULL"
                },
                "level": {
                    "type": "integer",
                    "null_value": "NULL"
                }
            }],
         ...
    }
}

比如我想过滤掉所有说英语且水平大于3和[=26=的人]日语 水平高于 2.

我已经尝试过的是这种方法并没有给出预期的结果。

"size": 1000,
"from": 0,
"query": {
  "bool": {
    "should": [
      {
        "bool": {
          "must": [
            {"match": {"languages.language": "english"}},
            {"range": {"languages.search_value": {"gt": 3}}}
          ]
        }
      },
      {
        "bool": {
          "must": [
            {"match": {"languages.language": "japanese"}},
            {"range": {"languages.search_value": {"gt": 2}}}
          ]
        }
      }
    ]
  }
}

以上查询returns所有说英语和日语的人,但语言水平不匹配。有些人会说 4 级英语(没问题),但日语会说 1 级(这不行),德语会说 5 级。我想问题在于,不是只为特定语言寻找想要的水平, 我的查询查找人们使用的所有语言的水平。

因此,我希望从查询中得到的结果是所有说英语 4 或 5 级和日语 3、4 或 5 级的人(都在同时)。我不关心他们说的其他语言和水平。

欢迎任何帮助或想法如何解决这个问题。

您需要使用 nested mapping 语言和级别。

映射

PUT /employee
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "languages": {
        "type": "nested",
        "properties": {
          "language": {
            "type": "text"
          },
          "level": {
            "type": "integer"
          }
        }
      }
    }
  }
}

数据:

 [
      {
        "_index" : "employee",
        "_type" : "_doc",
        "_id" : "vkVy9WwBecJvLwMRPgIH",
        "_score" : 1.0,
        "_source" : {
          "name" : "User1",
          "languages" : [
            {
              "language" : "English",
              "level" : 3
            },
            {
              "language" : "Japanese",
              "level" : 2
            }
          ]
        }
      },
      {
        "_index" : "employee",
        "_type" : "_doc",
        "_id" : "v0Vy9WwBecJvLwMRagL6",
        "_score" : 1.0,
        "_source" : {
          "name" : "User2",
          "languages" : [
            {
              "language" : "English",
              "level" : 3
            },
            {
              "language" : "Japanese",
              "level" : 1
            }
          ]
        }
      },
      {
        "_index" : "employee",
        "_type" : "_doc",
        "_id" : "wEVy9WwBecJvLwMRlQIs",
        "_score" : 1.0,
        "_source" : {
          "name" : "User3",
          "languages" : [
            {
              "language" : "English",
              "level" : 3
            },
            {
              "language" : "Spanish",
              "level" : 1
            }
          ]
        }
      },
      {
        "_index" : "employee",
        "_type" : "_doc",
        "_id" : "wUWD9WwBecJvLwMRWgIq",
        "_score" : 1.0,
        "_source" : {
          "name" : "User4",
          "languages" : [
            {
              "language" : "English",
              "level" : 2
            },
            {
              "language" : "French",
              "level" : 1
            }
          ]
        }
      }
    ]

查询

GET employee/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "languages",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "languages.language": "English"
                    }
                  },
                  {
                    "range": {
                      "languages.level": {
                        "gte": 3
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "languages",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "languages.language": "Japanese"
                    }
                  },
                  {
                    "range": {
                      "languages.level": {
                        "gte": 2
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

结果:

 [
      {
        "_index" : "employee",
        "_type" : "_doc",
        "_id" : "vkVy9WwBecJvLwMRPgIH",
        "_score" : 3.974081,
        "_source" : {
          "name" : "User1",
          "languages" : [
            {
              "language" : "English",
              "level" : 3
            },
            {
              "language" : "Japanese",
              "level" : 2
            }
          ]
        }
      }
    ]

解决方案非常简单,您需要了解嵌套类型。 Link 在这个答案中对此有解释