通过 ElasticSearch 6 中的子聚合进行过滤、排序和分页

Filtering, sorting and paginating by sub-aggregations in ElasticSearch 6

我有一个文件集,其中每个文件都表示给定酒店和日期的可用房间,以及当天的费用:

{
    "hotel_id": 2016021519381313,
    "day": "20200530",
    "rooms": [
        {
            "room_id": "00d70230ca0142a6874358919336e53f",
            "rate": 87
        },
        {
            "room_id": "675a5ec187274a45ae7a5fdc20f72201",
            "rate": 53
        }
    ]
}

作为映射:

{
    "properties": {
        "day": {
            "type": "keyword"
        },
        "hotel_id": {
            "type": "long"
        },
        "rooms": {
            "type": "nested",
            "properties": {
                "rate": {
                    "type": "long"
                },
                "room_id": {
                    "type": "keyword"
                }
            }
        }
    }
}

我想弄明白,如何进行查询,在其中我可以获得总费用低于给定金额的一组天数的可用房间,按总费用升序排列排序和分页。

到目前为止,我想出了在这组日子里获得可用房间的方法以及它们的总费用。基本上是按天过滤,按酒店和房间ID分组,要求聚合中的最小计数是我要查找的天数。

{
    "size" : 0,
    "query": {
        "bool": { 
            "must": [
                {
                    "terms" : {
                        "day" : ["20200423", "20200424", "20200425"]
                    }
                }
            ]
        } 
    } ,
    "aggs" : {
        "hotel" : {
            "terms" : { 
                "field" : "hotel_id"
            },
            "aggs" : {
                "rooms" : {
                    "nested" : {
                        "path" : "rooms"
                    },
                    "aggs" : {
                        "rooms" : {
                            "terms" : {
                                "field" : "rooms.room_id",
                                "min_doc_count" : 3
                            },
                            "aggs" : {
                                "sum_price" : { 
                                    "sum" : { "field" : "rooms.rate" } }
                            }
                        }

                    }
                }
            }
        }
    }
}

所以现在我感兴趣的是根据 "rooms" 子聚合的值在 "hotel" 级别对结果桶进行降序排序,并过滤不符合条件的桶包含足够的文档或 "sum_price" 超出给定预算。但是我不知道怎么做。

我一直在查看 "bucket_sort",但我找不到在子聚合基础上进行排序的方法。我也一直在查看 "bucket_selector",但当它们不符合谓词时,它会给我空桶。在我的情况下,我可能没有正确使用它们。

哪种方法才是正确的实现方式?

这里是查询没有分页:

{
   "size":0,
   "query":{
      "bool":{
         "must":[
            {
               "terms":{
                  "day":[
                     "20200530",
                     "20200531",
                     "20200532"
                  ]
               }
            }
         ]
      }
   },
   "aggs":{
      "rooms":{
         "nested":{
            "path":"rooms"
         },
         "aggs":{
            "rooms":{
               "terms":{
                  "field":"rooms.room_id",
                  "min_doc_count":3,
                  "order":{
                     "sum_price":"asc"
                  }
               },
               "aggs":{
                  "sum_price":{
                     "sum":{
                        "field":"rooms.rate"
                     }
                  },
                  "max_price":{
                     "bucket_selector":{
                        "buckets_path":{
                           "var1":"sum_price"
                        },
                        "script":"params.var1 < 100"
                     }
                  }
               }
            }
         }
      }
   }
}

请注意,应更改以下变量以获得所需的结果:

  • min_doc_count
  • max_price
  • 中的脚本