【问题标题】:Elasticsearch filter by nested fieldsElasticsearch 按嵌套字段过滤
【发布时间】:2020-09-24 14:41:00
【问题描述】:

我在创建包含许多条件的 Elasticsearch 查询时遇到问题。我的模型看起来像:

data class Product(
        @Id
        val id: String? = null,
        val category: String,
        val imagesUrls: List<String>,
        @Field(type = FieldType.Double)
        val price: Double?,
        @Field(type = FieldType.Nested)
        val parameters: List<Parameter>?
)

data class Parameter(
        val key: String,
        val values: List<String>
)

我想通过以下方式查询产品:

  • 类别(例如cars
  • 价格(在 20k $ 和 50k $ 之间)
  • 和参数->例如具有许多参数的产品,例如键capacity4L5L和第二参数齿轮传动值manual

我当前的查询如下所示:

GET data/_search
{

  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "category.keyword": {
              "value": "cars"
            }
          }
        },
        {
          "nested": {
            "path": "parameters",
            "query": {
              "bool": {
                "must": [
                  {"term": {
                    "parameters.key.keyword": {
                      "value": "Capacity"
                    }
                  }},
                  {
                    "term": {
                      "parameters.key": {
                        "value": "4L, 5L"
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
  • 能否告诉我如何在参数键等于容量时过滤产品并检查值列表是否包含其中一个值?
  • 如何在一个查询中组合多个此类操作?

示例数据:

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"capacity",
         "values":"4L"
      },
      {
         "key":"gear transmission",
         "values":"automcatic"
      }
   ]
}

【问题讨论】:

  • 你能分享一个示例 JSON 文档吗?
  • 是的,当然。刚刚添加。
  • @Ice 你有机会看我的回答吗,期待得到你的反馈:)
  • @BhavyaGupta 我看到了你的答案,明天我会检查它,当然,我会添加反馈:)
  • @Ice 您的赏金将在 11 小时内到期,如果您能仔细阅读我的回答,那就太好了,如果它帮助您解决问题,请不要忘记投票并接受我的回答您的查询:)

标签: elasticsearch


【解决方案1】:

下面显示的搜索查询根据以下条件查询数据:

  1. 类别(例如汽车)
  2. 和参数 -> 例如具有许多参数的产品,如关键容量值 4L、5L 和第二参数齿轮传动 价值观手册

添加一个包含索引数据、映射、搜索查询和搜索结果的工作示例

索引映射:

{
  "mappings": {
    "properties": {
      "parameters": {
        "type": "nested"
      }
    }
  }
}

索引数据:

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"gear transmission",
         "values":["4L","5L"]
      },
      {
         "key":"capacity",
         "values":"automcatic"
      }
   ]
}

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"capacity",
         "values":["4L","5L"]
      },
      {
         "key":"gear transmission",
         "values":"automcatic"
      }
   ]
}

{
   "category":"cars",
   "name":"Ferrari",
   "price":50000,
   "parameters":[
      {
         "key":"capacity",
         "values":"4L"
      },
      {
         "key":"gear transmission",
         "values":"automcatic"
      }
   ]
}

搜索查询:

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "category.keyword": {
              "value": "cars"
            }
          }
        },
        {
          "nested": {
            "path": "parameters",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "parameters.key": "capacity"
                    }
                  },
                  {
                    "terms": {
                      "parameters.values": [
                        "4l",
                        "5l"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "parameters",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "parameters.key": "gear transmission"
                    }
                  },
                  {
                    "match": {
                      "parameters.values": "automcatic"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

搜索结果:

"hits": [
         {
            "_index": "bstof",
            "_type": "_doc",
            "_id": "1",
            "_score": 3.9281754,
            "_source": {
               "category": "cars",
               "name": "Ferrari",
               "price": 50000,
               "parameters": [
                  {
                     "key": "capacity",
                     "values": "4L"
                  },
                  {
                     "key": "gear transmission",
                     "values": "automcatic"
                  }
               ]
            }
         },
         {
            "_index": "bstof",
            "_type": "_doc",
            "_id": "2",
            "_score": 3.9281754,
            "_source": {
               "category": "cars",
               "name": "Ferrari",
               "price": 50000,
               "parameters": [
                  {
                     "key": "capacity",
                     "values": [
                        "4L",
                        "5L"
                     ]
                  },
                  {
                     "key": "gear transmission",
                     "values": "automcatic"
                  }
               ]
            }
         }
      ]

【讨论】:

    【解决方案2】:

    当您需要匹配列表中的任何一个时,您可以使用terms 查询而不是term。从以下位置更新查询中的部分:

    {
      "term": {
        "parameters.key": {
          "value": "4L, 5L"
        }
      }
    }
    

    到下面:

    {
      "terms": {
        "parameters.values": {
          "value": [
            "4L",
            "5L"
          ]
        }
      }
    }
    

    请注意,如果 parameters.key 是分析字段并且存在相同的关键字子字段,则使用它来代替。例如parameters.values.keyword

    您可以阅读更多关于术语查询here

    【讨论】:

    • 但是您如何确保您在正确的键下检查参数值?对于具有capacity -> 4Lgear transmission" -> manual 的两辆车,此查询将如何显示?
    • 抱歉,一辆车有两个参数要查询。
    • 这就是应用的业务逻辑。
    • 不可能。它必须是在弹性搜索上执行此操作的一种方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    相关资源
    最近更新 更多