弹性搜索:嵌套属性中的Bool查询

时间:2017-12-01 15:22:43

标签: elasticsearch

让我们假设我的数据结构如下:

 { "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"
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
}

用“should”替换最高级别“must”会返回太多结果,这有意义,因为它转换为“或”。

2 个答案:

答案 0 :(得分:0)

使用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
            }
          }
        }
      ]
    }
  }
}

答案 1 :(得分:0)

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

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

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

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

我的索引映射如下:

                "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
                                        }
                                    ]
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },

这是浏览器的最终结果:

enter image description here