ElasticSearch 过滤多个字段(带聚合)

ElasticSearch filtering on multiple fields (with aggregration)

我正在为网上商店构建一个分面过滤功能,如下所示:

Filter on Brand:
[ ] LG (10)
[ ] Apple (5)
[ ] HTC (3)

Filter on OS:
[ ] Android 4 (11)
[ ] Android 5 (2)
[ ] IOS (5)

我在 elasticsearch 中使用聚合和过滤,在学习了几天 ES(爱它!)后,这对我来说效果很好。但遗憾的是我现在卡在了实际的过滤上。

如果我点击 'LG',IOS 过滤器将被禁用并且 (5) 将变为 (0),右侧的结果将变为 13 [=29= 】 手机。太好了,到目前为止一切顺利。

现在,如果我点击 'Android 4',右侧只会显示 11 部手机。惊人的!到目前为止一切顺利:)

但是现在,如果我点击 'Android 5',所有结果都会消失。我不确定我做错了什么。我希望所有 Android 4 和 5 的 LG 手机都能出现。

下面是最后一个案例的示例查询。请注意,我用来构建分面过滤的查询中还包含一些其他字段。

{
   "size":100,
   "query":{
      "filtered":{
         "query":{
            "match_all":[

            ]
         },
         "filter":{
            "bool":{
               "must":[
                  {
                     "term":{
                        "brand.untouched":"LG"
                     }
                  },
                  {
                     "term":{
                        "operating_system.untouched":"Android 4"
                     }
                  },
                  {
                     "term":{
                        "operating_system.untouched":"Android 5"
                     }
                  }
               ],
               "should":[

               ],
               "must_not":{
                  "missing":{
                     "field":"model"
                  }
               }
            }
         },
         "strategy":"query_first"
      }
   },
   "aggs":{
      "brand.untouched":{
         "terms":{
            "field":"brand.untouched"
         }
      },
      "operating_system.untouched":{
         "terms":{
            "field":"operating_system.untouched"
         }
      },
      "camera1":{
         "histogram":{
            "field":"camera1",
            "interval":5,
            "min_doc_count":0
         }
      },
      "price_seperate":{
         "histogram":{
            "field":"price_seperate",
            "interval":125,
            "min_doc_count":0
         }
      }
   }
}

有人知道解决办法吗?非常感谢。

您的查询正在搜索 operating_system.untouched 同时为 "Android 4" 和 "Android 5" 的文档,而这种情况永远不会发生,因此您得到零结果。您可以简单地使用 Terms Filter,以便匹配 operating_system.untouched 的值为 "Android 4" 或 "Android 5" 的文档。以下是您应该使用的更新查询:

{
   "size":100,
   "query":{
      "filtered":{
         "filter":{
            "bool":{
               "must":[
                  {
                     "terms":{
                        "brand.untouched": [
                            "LG"
                        ]
                     }
                  },
                  {
                     "terms":{
                        "operating_system.untouched": [
                            "Android 4",
                            "Android 5"
                        ]
                     }
                  }
               ],
               "must_not":{
                  "missing":{
                     "field":"model"
                  }
               }
            }
         },
         "strategy":"query_first"
      }
   },
   "aggs":{
      "brand.untouched":{
         "terms":{
            "field":"brand.untouched"
         }
      },
      "operating_system.untouched":{
         "terms":{
            "field":"operating_system.untouched"
         }
      },
      "camera1":{
         "histogram":{
            "field":"camera1",
            "interval":5,
            "min_doc_count":0
         }
      },
      "price_seperate":{
         "histogram":{
            "field":"price_seperate",
            "interval":125,
            "min_doc_count":0
         }
      }
   }
}

如果要添加另一组类别,如价格范围,只需在bool must 子句中添加一个bool should 子句即可。请参阅下面的示例,当您想要在两个范围 (0, 100](100, 200] 上筛选字段 price 时。这基本上意味着您可以嵌套 mustshould 过滤器来实现您想要在 Elasticsearch 中实现过滤的任何布尔逻辑。

... 
"must":[
    {
        "terms":{
            "brand.untouched": [
                "LG"
            ]
        }
    },
    {
        "terms":{
            "operating_system.untouched": [
               "Android 4",
               "Android 5"
            ]
        }
    },
    "bool": {
        "should": [
            {
                "range": {
                    "price": {
                        "gt": 0,
                        "lte": 100
                    }
                }
            },
            {
                "range": {
                    "price": {
                        "gt": 100,
                        "lte": 200
                    }
                }
            }
        ]
    }
],
...