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

MongoDB C#驱动:仅当foo更大时将bar更新为foo的值

问题描述

我有如下结构的MongoDB文档:

_id: ObjectId('deadbeefdeadbeefdeadbeef')
foo: 6
bar: 0

需求是:仅当foo的值大于bar时,将bar更新为foo的值。

尝试了两种常规更新方式都无法生效:

  1. 使用Max方法时,无法在更新语句中引用当前文档的foo字段:
_collection.UpdateMany(
    filter: document => true,
    update: Builders<MyDocument>.Update.Max(document => document.Bar, ___) // 无法在此处引用foo
);
  1. 尝试在过滤器中直接比较两个字段,驱动抛出异常:
_collection.UpdateMany(
    filter: document => document.Bar < document.Foo,
    update: Builders<MyDocument>.Update.Set(document => document.Bar, ___)
);
// System.ArgumentException: Unsupported filter: ({document}{bar} < {document}{foo})

使用的是MongoDB C#驱动2.13.0,找不到相关的内部字段引用资料,求优雅实现方式。

解决方案

在MongoDB 4.2及以上版本中,使用聚合管道执行更新是引用文档内部字段的最优方案,C#驱动2.13.0完全支持这种方式。

方法一:使用聚合管道构造更新

先通过过滤器筛选出bar < foo的文档,再用聚合管道的$set操作将bar赋值为foo:

// 构造跨字段比较的过滤器
var filter = Builders<MyDocument>.Filter.Lt(document => document.Bar, document => document.Foo);

// 用聚合管道定义更新逻辑,直接引用当前文档的foo字段
var update = Builders<MyDocument>.Update.Pipeline(
    new BsonDocument("$set", new BsonDocument("bar", "$foo"))
);

// 执行批量更新
_collection.UpdateMany(filter, update);

方法二:直接构造原生Bson更新语句

如果觉得管道写法繁琐,也可以用Raw方法传入原生Bson,效果一致:

var filter = Builders<MyDocument>.Filter.Lt("bar", "foo");
var update = Builders<MyDocument>.Update.Raw(
    new BsonDocument("$set", new BsonDocument("bar", "$foo"))
);

_collection.UpdateMany(filter, update);

关键说明

  • 之前过滤器报错的原因:不能直接在lambda表达式中写document.Bar < document.Foo,必须用驱动提供的FilterDefinitionBuilder方法(如Lt)来构造跨字段比较的过滤器。
  • 聚合管道更新的优势:支持直接引用当前文档的字段值,无需提前查询字段内容,原子性执行更新操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:40:26