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
相关产品推荐
相关产品推荐

