【问题标题】:ElasticSearch filtering on multiple fields (with aggregration)ElasticSearch 过滤多个字段(带聚合)
【发布时间】:2015-07-12 11:59:07
【问题描述】:

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

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 部安卓手机。太好了,到目前为止一切顺利。

现在如果我点击“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
         }
      }
   }
}

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

【问题讨论】:

    标签: json elasticsearch facet nosql


    【解决方案1】:

    您的查询正在搜索其中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
                        }
                    }
                }
            ]
        }
    ],
    ...
    

    【讨论】:

    • 谢谢,这行得通!我不敢相信我在文档中错过了这一点。对我来说是嘘声。现在唯一还在唠叨的是范围。假设我添加了价格范围 0-100 和价格范围 200-300。看来我不能将它们都添加到过滤器中......有什么想法吗?
    • 是的,你可以。只需添加一个bool should 子句,其中包含range 过滤器。这个bool should 子句必须在bool must 子句内。我会更新答案。
    • 用过滤多个价格范围场景的解决方案更新了我的答案。
    猜你喜欢
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    相关资源
    最近更新 更多