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

如何通过locationId和customerId提取指定客户的预约记录?

MongoDB查询:仅获取指定locationId和customerId的预约记录

场景与问题

给定如下客户预约数据集(顶层包含locationId):

[
    {
        "locationId": 9999,
        "customerAppointments": [
            {
                "customerId": "1",
                "appointments": [
                    {
                        "appointmentId": "cbbce566-da59-42c2-8845-53976ba63d56",
                        "locationName": "Sullivan St"
                    },
                    {
                        "appointmentId": "5f09e2af-ddae-47aa-9f7c-fd1001a9c5e6",
                        "locationName": "Oak St"
                    }
                ]
            },
            {
                "customerId": "2",
                "appointments": [
                    {
                        "appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
                        "locationName": "Kellet St"
                    }
                ]
            },
            {
                "customerId": "3",
                "appointments": []
            }
        ]
    },
    { ... },
    { ... }
]

需求是通过locationId和customerId提取对应客户的预约记录,期望输出示例:

[
    {
        "appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
        "locationName": "Kellet St"
    }
]

尝试了以下查询语句,但返回了包含所有客户记录的完整文档:

db.getCollection("appointments").find(
    {
        "locationId" : NumberInt(9999),
        "customerAppointments" : {
            "$elemMatch" : {
                "customerId" : "2"
            }
        }
    });

原因说明

上述查询中的$elemMatch仅用于匹配包含符合条件元素的文档,不会过滤数组中其他不匹配的元素,因此返回的是整个包含目标locationId的文档,而非仅目标客户的预约记录。

解决方案

方法一:使用聚合管道(推荐,支持复杂场景)

通过聚合管道逐步筛选、拆分和提取目标数据:

db.getCollection("appointments").aggregate([
    // 1. 筛选出指定locationId的文档
    { $match: { locationId: NumberInt(9999) } },
    // 2. 拆分customerAppointments数组,每个元素独立成文档
    { $unwind: "$customerAppointments" },
    // 3. 筛选出指定customerId的客户数据
    { $match: { "customerAppointments.customerId": "2" } },
    // 4. 将目标appointments数组转为顶层文档(若有多个预约则返回数组)
    { $replaceRoot: { newRoot: { $first: "$customerAppointments.appointments" } } }
])

如果需要保留预约数组结构(即使只有一条记录),可以调整最后一步:

db.getCollection("appointments").aggregate([
    { $match: { locationId: NumberInt(9999) } },
    { $unwind: "$customerAppointments" },
    { $match: { "customerAppointments.customerId": "2" } },
    { $project: { _id: 0, appointments: "$customerAppointments.appointments" } },
    { $unwind: "$appointments" },
    { $replaceRoot: { newRoot: "$appointments" } }
])

方法二:使用投影(Projection)结合位置操作符

通过查询+投影定位目标元素,再通过map提取最终数据:

db.getCollection("appointments").find(
    {
        locationId: NumberInt(9999),
        "customerAppointments.customerId": "2"
    },
    {
        _id: 0,
        "customerAppointments.$.appointments": 1
    }
).map(doc => doc.customerAppointments[0].appointments)[0]

这里的$位置操作符会返回数组中第一个匹配customerId的元素,再通过map提取出其中的appointments数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:18:23