You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elasticsearch:查询日期区间内预订量总和小于可用量的房间

问题描述

我的房间文档结构如下:

{
    "availability": 3,
    "bookings": [
        {
            "booking_interval": {
                "lt": "2024-05-16",
                "gte": "2024-05-09"
            },
            "quantity": 1
        },
        {
            "booking_interval": {
                "lt": "2024-06-10",
                "gte": "2024-06-01"
            },
            "quantity": 1
        },
        {
            "booking_interval": {
                "lt": "2024-06-12",
                "gte": "2024-06-02"
            },
            "quantity": 2
        }
    ]
}

需求:搜索指定日期区间,当该区间内匹配到的预订记录的quantity字段总和小于availability字段值时,判定该房型可用并返回。

我当前尝试的nested查询只能匹配日期区间,无法判断预订量总和:

{
    "nested": {
        "path": "bookings",
        "query": {
            "bool": {
                "must": [
                    {
                        "range": {
                            "bookings.booking_interval": {
                                "gte": "2024-06-04",
                                "lt": "2024-06-06"
                            }
                        }
                    }
                ]
            }
        }
    }
}

举个实际场景:

  • 2024-06-04至2024-06-06区间有2笔预订(数量1和2),总和3等于可用量3,不应返回结果;
  • 2024-05-09至2024-05-16区间仅1笔预订,剩余2间可用,应返回结果。
解决方案

要实现预订量总和的判断,需要结合nested查询和script脚本计算符合条件的预订数量总和,再与availability做比较。以下是两种可行的查询方案:

方案1:全量脚本遍历(适合数据量不大的场景)

{
    "query": {
        "bool": {
            "filter": [
                {
                    "script": {
                        "script": {
                            "source": """
                                int total = 0;
                                for (def booking : params._source.bookings) {
                                    // 判断预订区间与目标区间是否重叠
                                    if (booking.booking_interval.gte < params.end && booking.booking_interval.lt > params.start) {
                                        total += booking.quantity;
                                    }
                                }
                                return total < params._source.availability;
                            """,
                            "params": {
                                "start": "2024-06-04",
                                "end": "2024-06-06"
                            }
                        }
                    }
                }
            ]
        }
    }
}

逻辑说明:

  1. 脚本遍历所有bookings记录;
  2. 判断每个预订的区间是否与目标查询区间重叠(覆盖包含、交叉等所有重叠场景);
  3. 累加所有重叠预订的quantity;
  4. 最后判断累加结果是否小于availability,满足条件则返回该文档。

方案2:先过滤再计算(性能更优)

先通过nested查询缩小范围,再用脚本计算总和,适合数据量较大的场景:

{
    "query": {
        "bool": {
            "filter": [
                {
                    "bool": {
                        "should": [
                            // 处理无任何预订的情况
                            {
                                "bool": {
                                    "must_not": {
                                        "exists": {
                                            "field": "bookings"
                                        }
                                    }
                                }
                            },
                            // 处理有重叠预订但总和小于可用量的情况
                            {
                                "bool": {
                                    "must": [
                                        {
                                            "nested": {
                                                "path": "bookings",
                                                "query": {
                                                    "range": {
                                                        "bookings.booking_interval": {
                                                            "lt": "2024-06-06",
                                                            "gte": "2024-06-04"
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        {
                                            "script": {
                                                "script": {
                                                    "source": """
                                                        int total = 0;
                                                        for (def booking : params._source.bookings) {
                                                            if (booking.booking_interval.gte < params.end && booking.booking_interval.lt > params.start) {
                                                                total += booking.quantity;
                                                            }
                                                        }
                                                        return total < params._source.availability;
                                                    """,
                                                    "params": {
                                                        "start": "2024-06-04",
                                                        "end": "2024-06-06"
                                                    }
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}

逻辑说明:

  1. 先通过nested查询筛选出存在重叠预订的文档;
  2. 再用脚本计算这些文档的重叠预订总量,判断是否小于可用量;
  3. 同时兼容无任何预订的文档(这类文档默认可用)。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 05:05:02