按多个嵌套属性过滤

时间:2020-11-04 11:10:45

标签: elasticsearch

我有这样的索引定义:

    {
      "settings": {
        "index": {
          "number_of_shards": 1,
          "number_of_replicas": 0
        },
      },
      "mappings": {
        "properties": {
          "parameters_for_filter": {
            "type": "nested",
            "properties": {
              "parameters": {
                "type": "nested",
                "properties": {
                  "parameter_id": {
                    "type": "integer"
                  },
                  "parameter_value_id": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      }
    }

这是一种产品的导出结果:

    {
      "_index": "product_1_9107bbdeb03269e1142d9822e585008c",
      "_type": "_doc",
      "_id": "69",
      "_version": 1,
      "_score": 0,
      "_source": {
        "id": 69,
        "parameters_for_filter": {
          "parameters": [
            [
              {
                "parameter_id": 5,
                "parameter_value_id": 10
              },
              {
                "parameter_id": 3,
                "parameter_value_id": 251
              },
              {
                "parameter_id": 1,
                "parameter_value_id": 248
              }
            ],
            [
              {
                "parameter_id": 5,
                "parameter_value_id": 16
              },
              {
                "parameter_id": 3,
                "parameter_value_id": 251
              },
              {
                "parameter_id": 1,
                "parameter_value_id": 254
              }
            ]
          ]
        }
      }
    }

另一种产品:

{
  "_index": "product_1_9107bbdeb03269e1142d9822e585008c",
  "_type": "_doc",
  "_id": "83",
  "_version": 5,
  "_score": 0,
  "_source": {
    "id": 83,
    "parameters_for_filter": {
      "parameters": [
        [
          {
            "parameter_value_id": 10,
            "parameter_id": 5
          },
          {
            "parameter_value_id": 251,
            "parameter_id": 3
          },
          {
            "parameter_value_id": 254,
            "parameter_id": 1
          }
        ],
        [
          {
            "parameter_value_id": 16,
            "parameter_id": 5
          },
          {
            "parameter_value_id": 121,
            "parameter_id": 2
          },
          {
            "parameter_value_id": 254,
            "parameter_id": 1
          }
        ]
      ]
    }
  }
}

parameters_for_filter.parameters中的每个子数组代表产品各个变体的参数。

我需要做的是获取ID为69的产品以用于过滤器组合:

{{parameter_id: 5, parameter_value_id: 10}, {parameter_id: 1, parameter_value_id: 248}}

获取ID为83的产品以用于过滤器组合:

{{parameter_id: 5, parameter_value_id: 10}, {parameter_id: 1, parameter_value_id: 254}}

同时获取两种产品以使用过滤器:

{{parameter_id: 5, parameter_value_id: 16}, {parameter_id: 1, parameter_value_id: 254}}

没有获得用于过滤器组合的产品:

{{parameter_id: 5, parameter_value_id: 16}, {parameter_id: 1, parameter_value_id: 248}}

通过当前查询,我获得了具有以上所有3种组合的产品:

{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": [
        {
          "nested": {
            "path": "parameters_for_filter.parameters",
            "query": {
              "bool": {
                "must": {
                  "match_all": {}
                },
                "filter": [
                  {
                    "term": {
                      "parameters_for_filter.parameters.parameter_id": 5
                    }
                  },
                  {
                    "terms": {
                      "parameters_for_filter.parameters.parameter_value_id": [
                        10
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "parameters_for_filter.parameters",
            "query": {
              "bool": {
                "must": {
                  "match_all": {}
                },
                "filter": [
                  {
                    "term": {
                      "parameters_for_filter.parameters.parameter_id": 1
                    }
                  },
                  {
                    "terms": {
                      "parameters_for_filter.parameters.parameter_value_id": [
                        248
                      ]
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

满足我所需条件的过滤器会是什么样子?或者我可以在eshop中使用更好的结构作为产品变型的参数(不将变体导出为单独的对象)?

2 个答案:

答案 0 :(得分:1)

添加包含索引数据,搜索查询和搜索结果的工作示例(使用与所给出的映射相同的映射)

如果您想忽略计分,可以使用filter子句代替must子句

索引数据:

{
  "id": 69,
  "parameters_for_filter": {
    "parameters": [
      [
        {
          "parameter_id": 5,
          "parameter_value_id": 10
        },
        {
          "parameter_id": 3,
          "parameter_value_id": 251
        },
        {
          "parameter_id": 1,
          "parameter_value_id": 254
        }
      ]
    ]
  }
}
{
  "id": 69,
  "parameters_for_filter": {
    "parameters": [
      [
        {
          "parameter_id": 5,
          "parameter_value_id": 10
        },
        {
          "parameter_id": 3,
          "parameter_value_id": 251
        },
        {
          "parameter_id": 1,
          "parameter_value_id": 248
        }
      ]
    ]
  }
}
{
  "id": 69,
  "parameters_for_filter": {
    "parameters": [
      [
        {
          "parameter_id": 5,
          "parameter_value_id": 10
        },
        {
          "parameter_id": 3,
          "parameter_value_id": 251
        },
        {
          "parameter_id": 1,
          "parameter_value_id": 247
        }
      ]
    ]
  }
}

搜索查询:

{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must": [
              {
                "nested": {
                  "path": "parameters_for_filter.parameters",
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_id": 5
                          }
                        },
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_value_id": 10
                          }
                        }
                      ]
                    }
                  }
                }
              },
              {
                "nested": {
                  "path": "parameters_for_filter.parameters",
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_id": 1
                          }
                        },
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_value_id": 248
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "nested": {
                  "path": "parameters_for_filter.parameters",
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_id": 5
                          }
                        },
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_value_id": 16
                          }
                        }
                      ]
                    }
                  }
                }
              },
              {
                "nested": {
                  "path": "parameters_for_filter.parameters",
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_id": 1
                          }
                        },
                        {
                          "match": {
                            "parameters_for_filter.parameters.parameter_value_id": 254
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

搜索结果:

"hits": [
      {
        "_index": "64678935",
        "_type": "_doc",
        "_id": "2",
        "_score": 4.0,
        "_source": {
          "id": 69,
          "parameters_for_filter": {
            "parameters": [
              [
                {
                  "parameter_id": 5,
                  "parameter_value_id": 10
                },
                {
                  "parameter_id": 3,
                  "parameter_value_id": 251
                },
                {
                  "parameter_id": 1,
                  "parameter_value_id": 248
                }
              ]
            ]
          }
        }
      }
    ]

答案 1 :(得分:1)

我们必须以某种方式让ES知道parameters确实是不同的属性组,并且通过仔细检查,似乎发现有一对额外的括号[ ]包围了这些参数,实际上使嵌套无效-ness b / c一切都是一个大数组。

我的建议如下:由于parameters_for_filter是一个恰好由1个孩子组成的对象,因此我们将其默认设置为简单的object,并将添加一层嵌套隔离我称之为parameter_groups的地方。 因此映射将如下所示:

PUT eshop
{
  "settings": {
    "index": {
      "number_of_shards": 1,
      "number_of_replicas": 0
    }
  },
  "mappings": {
    "properties": {
      "parameters_for_filter": {
        "type": "object",                <--
        "properties": {
          "parameters": {
            "type": "nested",
            "properties": {
              "parameter_groups": {      <---
                "type": "nested",
                "properties": {
                  "parameter_id": {
                    "type": "integer"
                  },
                  "parameter_value_id": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

之后,让我们同步2个文档。请注意,参数组在逻辑上是分开的:

POST eshop/_doc
{
  "id": 69,
  "parameters_for_filter": {
    "parameters": [
      {
        "parameter_groups": [
          {
            "parameter_id": 5,
            "parameter_value_id": 10
          },
          {
            "parameter_id": 3,
            "parameter_value_id": 251
          },
          {
            "parameter_id": 1,
            "parameter_value_id": 248
          }
        ]
      },
      {
        "parameter_groups": [
          {
            "parameter_id": 5,
            "parameter_value_id": 16
          },
          {
            "parameter_id": 3,
            "parameter_value_id": 251
          },
          {
            "parameter_id": 1,
            "parameter_value_id": 254
          }
        ]
      }
    ]
  }
}

还有id:83

POST eshop/_doc
{
  "id": 83,
  "parameters_for_filter": {
    "parameters": [
      {
        "parameter_groups": [
          {
            "parameter_value_id": 10,
            "parameter_id": 5
          },
          {
            "parameter_value_id": 251,
            "parameter_id": 3
          },
          {
            "parameter_value_id": 254,
            "parameter_id": 1
          }
        ]
      },
      {
        "parameter_groups": [
          {
            "parameter_value_id": 16,
            "parameter_id": 5
          },
          {
            "parameter_value_id": 121,
            "parameter_id": 2
          },
          {
            "parameter_value_id": 254,
            "parameter_id": 1
          }
        ]
      }
    ]
  }
}

此后,我们将继续进行查询,以查找两个条件的must组合,尽管在单独的parameter_groups路径下:

GET eshop/_search
{
  "query": {
    "nested": {
      "path": "parameters_for_filter.parameters",
      "query": {
        "bool": {
          "must": [
            {
              "nested": {
                "path": "parameters_for_filter.parameters.parameter_groups",
                "query": {
                  "bool": {
                    "must": [
                      {
                        "term": {
                          "parameters_for_filter.parameters.parameter_groups.parameter_id": 5
                        }
                      },
                      {
                        "terms": {
                          "parameters_for_filter.parameters.parameter_groups.parameter_value_id": [
                            16
                          ]
                        }
                      }
                    ]
                  }
                }
              }
            },
            {
              "nested": {
                "path": "parameters_for_filter.parameters.parameter_groups",
                "query": {
                  "bool": {
                    "must": [
                      {
                        "term": {
                          "parameters_for_filter.parameters.parameter_groups.parameter_id": 1
                        }
                      },
                      {
                        "terms": {
                          "parameters_for_filter.parameters.parameter_groups.parameter_value_id": [
                            248
                          ]
                        }
                      }
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    }
  }
}

从而满足您所有的4个要求。

相关问题