【问题标题】:Filtering on multiple fields from nested object with Elasticsearch使用 Elasticsearch 从嵌套对象中过滤多个字段
【发布时间】:2019-09-02 13:58:51
【问题描述】:

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

这是 Elasticsearch 中映射的一部分:

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

例如,我想过滤掉所有说 English 级别大于 3Japanese 级别大于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}}}
          ]
        }
      }
    ]
  }
}

上述查询返回所有会说英语和日语的人,但语言的级别不匹配。有些人说英语 4 级(可以),但日语 1 级(不行)和德语 5 级。我想问题是,而不是只为指定的语言寻找想要的水平,我的查询会查找人们使用的所有口语的级别。

所以,我期望从查询中得到的结果是让所有说英语的人达到 4 或 5 级,日语达到 3、4 或 5 级(两者同时进行强>)。我不在乎他们说的其他语言和他们的水平。

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

【问题讨论】:

    标签: elasticsearch kibana elasticsearch-query


    【解决方案1】:

    语言和级别需要使用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
                }
              ]
            }
          }
        ]
    

    解决方法很简单,你需要了解嵌套类型。此答案中的链接对此进行了解释

    【讨论】:

    • 好的,所以我在映射中进行了必要的更改,但是当我执行查询时,我得到以下异常:“type”:“illegal_state_exception”,“reason”:“[nested]路径 [languages] 下的嵌套对象不是嵌套类型”
    • 根据异常映射看起来没有更新。你能粘贴你的映射和查询吗
    • "languages": { "type": "nested", "properties": { "language": { "type": "text", "null_value": "NULL" }, "level": { "type": "integer", "null_value": "NULL" } }查询和你的一样
    • "null_value": "NULL" 不允许用于文本和整数类型(必须给你错误)。我尝试通过将类型更改为关键字来指定 "null_value": "NULL" 并尝试查询,它正在返回数据。尝试 GET /_mapping 它应该提供映射并验证映射是否正在更新
    • 是的,我遇到了映射问题(未显示的错误),但最终我解决了它们。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    相关资源
    最近更新 更多