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

如何从MongoDB聚合$group阶段的_id中提取分组字段为独立字段

MongoDB聚合查询:将_id内的分组字段提取到顶层

我的MongoDB聚合查询中,$group阶段代码如下:

$group:
{
    _id: 
    { 
        year_month: { $dateToString: { "date": "$updated_at", "format": "%Y-%m"  } } 
        ,client_name: "$clients_docs.client_name"
        ,client_label: "$clients_docs.client_label"
        ,client_code: "$clients_docs.client_code"
        ,client_country: "$clients_docs.client_country"
        ,base_curr: "$clients_docs.client_base_currency"
        ,inv_curr: "$clients_docs.client_invoice_currency" 
        ,dest_curr: "$store.destination_currency"                       
    }
    ,total_vol: { $sum: "$USD_Value" }
    ,total_tran: { $sum: 1 }
}                 

该阶段返回结果正确,但所有分组字段都嵌套在_id对象中。我尝试添加了一个$project阶段:

{
    $project:
    {
        year_month: 1
        ,client_name: 1
        ,client_label: 1
        ,client_code: 1
        ,client_country: 1
        ,base_curr: 1
        ,inv_curr: 1         
        ,dest_curr: 1
        ,total_vol: 1
        ,total_tran : 1
    }
},

但结果与$group阶段一致,分组字段仍在_id内:

{
    "_id" : {
        "year_month" : "2022-01",
        "client_name" : "client A",
        "client_label" : "client A",
        "client_code" : NumberInt(0000),
        "client_country" : "TH",
        "base_curr" : "USD",
        "inv_curr" : "USD",
        "dest_curr" : "HKD"
    },
    "total_vol" : 100000,
    "total_tran" : 100.0
}

我需要将year_month至dest_curr字段与total_vol、total_tran置于同一层级,方便导出到电子表格时成为独立列。


可行解决方案

方案1:用$replaceRoot一键合并字段

在$group阶段后添加$replaceRoot阶段,将_id内的字段与顶层统计字段合并为新的根文档,自动移除原_id:

{
    $replaceRoot: {
        newRoot: {
            $mergeObjects: [ "$_id", { total_vol: "$total_vol", total_tran: "$total_tran" } ]
        }
    }
}

执行后会得到目标格式的文档:

{
    "year_month" : "2022-01",
    "client_name" : "client A",
    "client_label" : "client A",
    "client_code" : NumberInt(0000),
    "client_country" : "TH",
    "base_curr" : "USD",
    "inv_curr" : "USD",
    "dest_curr" : "HKD",
    "total_vol" : 100000,
    "total_tran" : 100.0
}

方案2:$addFields+$project分步处理

如果需要更精细的字段控制,可以先通过$addFields将_id内的字段提取到顶层,再用$project移除_id:

// 第一步:提取_id内的字段到顶层
{
    $addFields: {
        year_month: "$_id.year_month",
        client_name: "$_id.client_name",
        client_label: "$_id.client_label",
        client_code: "$_id.client_code",
        client_country: "$_id.client_country",
        base_curr: "$_id.base_curr",
        inv_curr: "$_id.inv_curr",
        dest_curr: "$_id.dest_curr"
    }
},
// 第二步:移除_id,保留需要的顶层字段
{
    $project: {
        _id: 0,
        year_month: 1,
        client_name: 1,
        client_label: 1,
        client_code: 1,
        client_country: 1,
        base_curr: 1,
        inv_curr: 1,
        dest_curr: 1,
        total_vol: 1,
        total_tran: 1
    }
}

原$project失效原因

之前的$project直接指定字段名,但这些字段实际嵌套在_id对象中,MongoDB无法直接识别顶层的year_month等字段,必须明确从_id中引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:35:21