【问题标题】:Elastic Search: Bool Query in nested properties弹性搜索:嵌套属性中的布尔查询
【发布时间】:2017-12-18 17:36:08
【问题描述】:

假设我的数据结构如下:

 { "id": "120400871755634330808993320",
                    "name": "Metaalschroef binnenzeskant, DIN 912 RVS A4-80",
                    "description": "m16x70 cilinderschroef bzk a4-80 din912 klasse 80",
                    "fullDescription": "Metaalschroef met een binnenzeskant cilinderkop",
                    "synonyms": [],
                    "properties": [
                        {
                            "name": "draad",
                            "value": "16",
                            "sort": 99
                        },
                        {
                            "name": "lengte",
                            "value": "70",
                            "sort": 99
                        },
                        {
                            "name": "materiaal",
                            "value": "roestvaststaal",
                            "sort": 99
                        },
                        {
                            "name": "kwaliteit (materiaal)",
                            "value": "A4",
                            "sort": 99
                        },
                        {
                            "name": "DIN",
                            "value": "912",
                            "sort": 99
                        },
                        {
                            "name": "AISI",
                            "value": "316",
                            "sort": 99
                        },
                        {
                            "name": "draadsoort",
                            "value": "metrisch",
                            "sort": 99
                        },
                        {
                            "name": "Merk",
                            "value": "Elcee Holland",
                            "sort": 1
                        }
                    ]
}

如何编写一个布尔查询,在其中选择具有名称为“draad”且值为“16”的属性以及名称为“lengte”且值为“70”的属性的所有文档。

现在我有这个,但它返回 0 个结果:

"query" : {
    "nested" : {
        "path" : "properties",
        "query" : {
            "bool" : {
                "must" : [{
                        "bool" : {
                            "must" : [{
                                    "term" : {
                                        "properties.name" : "Merk"
                                    }
                                }, {
                                    "term" : {
                                        "properties.value" : "Facom"
                                    }
                                }
                            ]
                        }
                    }, {
                        "bool" : {
                            "must" : [{
                                    "term" : {
                                        "properties.name" : "materiaal"
                                    }
                                }, {
                                    "term" : {
                                        "properties.value" : "kunststof"
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
}

将最高级别的“必须”替换为“应该”会返回太多结果,这是有道理的,因为它会转化为“或”。

【问题讨论】:

  • 你能添加你的映射吗?

标签: elasticsearch


【解决方案1】:

使用must 时,引擎会尝试使用name:Merkvalue:Facom 搜索嵌套文档。但也可以使用 name:materiaalvalue:kunststof - 这不可能同时发生在同一个嵌套文档中。

当您提到使用should 时,它会转换为or - 这确实是可能的。

问题是,您还可以获取整个父文档及其所有嵌套文档。

在我自己的answer 中,我展示了使用nested 文档创建索引的步骤(您应该将字段properties 标记为嵌套类型`)。

完成这些步骤后,您将能够通过以下查询获得结果:

{
  "_source": [
    "id",
    "name",
    "description"
  ],
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "properties",
            "query": {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "must": [
                        {
                          "term": {
                            "properties.name": "Merk"
                          }
                        },
                        {
                          "term": {
                            "properties.value": "Facom"
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "must": [
                        {
                          "term": {
                            "properties.name": "materiaal"
                          }
                        },
                        {
                          "term": {
                            "properties.value": "kunststof"
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            },
            "inner_hits":{
              "size": 10
            }
          }
        }
      ]
    }
  }
}

【讨论】:

  • 你好 Eli,我已经尝试了你的建议,但我仍然得到结果,就好像它是一个 OR 查询一样。
  • 我想我错过了你的意思。你可以为你期望得到的结果添加一个例子吗? (根据你上面的数据)
  • 我已经通过在属性数组中添加一个新属性来解决它,它是名称和值的组合。例如:材料艺术。这使我可以使用这样的查询进行搜索:{ "term": { "properties.slug": "materiaal-kunststof" } }
【解决方案2】:

我找到了一个效果很好的解决方案!

我的属性对象现在看起来像这样:

                    {
                        "name": "breedte(mm)",
                        "value": "1000",
                        "unit": "mm",
                        "sort": 99,
                        "nameSlug": "breedte-mm",
                        "slug": "breedte-mm-1000"
                    },

我添加了一个 slug(包含 key + value 的规范化字符串)和一个 nameslug,它是名称的规范化字符串。

我的索引是这样映射的:

                "properties": {
                    "type": "nested",
                    "include_in_parent": true,
                    "properties": {
                        "name": {
                            "type": "keyword"
                        },
                        "nameSlug": {
                            "type": "keyword"
                        },
                        "slug": {
                            "type": "keyword"
                        },
                        "sort": {
                            "type": "long"
                        },
                        "unit": {
                            "type": "text",
                            "index": false
                        },
                        "value": {
                            "type": "keyword"
                        }
                    }
                }

“include_in_parent”在这里很重要。它允许我进行以下查询:

"query": {
    "bool": {
      "must": [
        {
          "terms": {
            "properties.slug": [
              "merk-orbis",
              "merk-bahco"
            ]
          }
        },
        {
          "terms": {
            "properties.slug": [
              "materiaal-staal",
              "materiaal-kunststof"
            ]
          }
        }
      ]
    }
  },

此查询搜索“merk”为“Orbis”或“Bahco”以及“materiaal”为“staal”或“kunststof”的所有文档。

我的聚合如下所示:

"merk_query": {
          "filter": {
            "bool": {
              "must": [
                {
                  "terms": {
                    "properties.slug": [
                      "materiaal-staal",
                      "materiaal-kunststof"
                    ]
                  }
                }
              ]
            }
          },
          "aggs": {
            "merk_facets": {
              "nested": {
                "path": "properties"
              },
              "aggs": {
                "merk_only": {
                  "filter": {
                    "term": {
                      "properties.nameSlug": {
                        "value": "merk"
                      }
                    }
                  },
                  "aggs": {
                    "facets": {
                      "terms": {
                        "field": "properties.name",
                        "size": 1
                      },
                      "aggs": {
                        "facetvalues": {
                          "terms": {
                            "field": "properties.value",
                            "size": 10
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },

我运行 filteraggregate 过滤所有匹配一个方面的文档(但不是我正在构建的当前文档)。

这个聚合的结果是这样的:

"merk_query": {
                "doc_count": 7686,
                "merk_facets": {
                    "doc_count": 68658,
                    "merk_only": {
                        "doc_count": 7659,
                        "facets": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "Merk",
                                    "doc_count": 7659,
                                    "facetvalues": {
                                        "doc_count_error_upper_bound": 10,
                                        "sum_other_doc_count": 438,
                                        "buckets": [
                                        {
                                            "key": "Orbis",
                                            "doc_count": 6295
                                        },
                                        {
                                            "key": "DX",
                                            "doc_count": 344
                                        },
                                        {
                                            "key": "AXA",
                                            "doc_count": 176
                                        },
                                        {
                                            "key": "Talen Tools",
                                            "doc_count": 127
                                        },
                                        {
                                            "key": "Nemef",
                                            "doc_count": 73
                                        },
                                        {
                                            "key": "bonfix",
                                            "doc_count": 67
                                        },
                                        {
                                            "key": "Bahco",
                                            "doc_count": 64
                                        },
                                        {
                                            "key": "Henderson",
                                            "doc_count": 27
                                        },
                                        {
                                            "key": "Maasland Groep",
                                            "doc_count": 25
                                        },
                                        {
                                            "key": "SYSTEC",
                                            "doc_count": 23
                                        }
                                    ]
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },

这是浏览器中的最终结果:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 2015-09-24
    • 2020-07-26
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多