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

MongoDB:如何仅在条件为True时用$cond替换指定字段并保留原结构

问题描述

原始文档示例:

{
    _id: 1,
    status: "estimate.sent",
    request_info: {request_id: 1, request_status: "done"},
    estimate_info: {
        estimate_id: 1,
        estimate_status: "sent",
        expire_date: "2022-12-08T05:49:56.908149"
    }
}

我要实现的逻辑是:当estimate_info.expire_date早于当前UTC时间时,把estimate_info.estimate_status的值改成"expired"。

目前用PyMongo写了这段聚合查询:

today = datetime.utcnow()
db.collection.aggregate(
    [
        {$match: {_id: 1}},
        {$addFields: {
            "estimate_info.estimate_status": {$cond: [
                {$and: [
                    {$eq: ["$status", "estimate.sent"]},
                    {$lt: ["$estimate_info.expire_date", today]}
                    ]
                }, "expired", "$estimate_info.estimate_status"]
            }}
        }
    ]
)

这段代码在条件满足时能正常工作,但有个问题:我希望$cond条件不满足时完全不修改字段,但现在当status不等于"estimate.sent"时,estimate_info会变成空对象{},而不是保持原本的null值。


解决方案

聚合查询场景(仅返回修改结果,不更新数据库)

不要直接修改嵌套子字段,而是通过整体判断来替换estimate_info字段,这样条件不满足时会保留原字段的状态(包括null),不会生成空对象:

from datetime import datetime

today = datetime.utcnow()
db.collection.aggregate(
    [
        {"$match": {"_id": 1}},
        {"$addFields": {
            "estimate_info": {
                "$cond": [
                    {"$and": [
                        {"$eq": ["$status", "estimate.sent"]},
                        {"$lt": ["$estimate_info.expire_date", today]}
                    ]},
                    # 条件满足时,合并原对象与新状态
                    {"$mergeObjects": [
                        "$estimate_info",
                        {"estimate_status": "expired"}
                    ]},
                    # 条件不满足时,直接返回原estimate_info
                    "$estimate_info"
                ]
            }
        }}
    ]
)

直接更新数据库场景

如果需要直接修改数据库中的文档,用update_one更合适,只有条件满足时才执行更新,完全不会影响不满足条件的文档:

today = datetime.utcnow()
db.collection.update_one(
    {"_id": 1},
    {"$set": {
        "estimate_info.estimate_status": "expired"
    }},
    array_filters=[
        {"$and": [
            {"$eq": ["$status", "estimate.sent"]},
            {"$lt": ["$estimate_info.expire_date", today]}
        ]}
    ]
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:45:29