MongoDB .NET Driver:字典内值的原子递增实现问题
解决MongoDB C#驱动中字典值原子递增的问题
错误原因
你之前的代码里多了.v后缀,这是错误的。因为C#中的Dictionary<int, int>在MongoDB中会被序列化为直接的键值对文档结构,比如:
"totalViewsPerUser": { "1001": 3, "1002": 1 }
不存在嵌套的v子字段,所以.Inc($"totalViewsPerUser.{userId}.v", 1)找不到对应路径,自然无法插入新键或递增现有值。
正确实现方式
方式1:使用表达式树(推荐,编译时校验)
利用MongoDB驱动的表达式树支持,直接通过字典索引指定要操作的键,无需硬编码字符串:
var update = Builders<OrderDetails>.Update .Inc(x => x.TotalViewsPerUser[userId], 1);
方式2:使用字符串路径(注意命名约定)
如果你的实体类序列化采用默认驼峰命名(C#属性TotalViewsPerUser对应MongoDB中的totalViewsPerUser),可以直接写路径字符串:
var update = Builders<OrderDetails>.Update .Inc($"totalViewsPerUser.{userId}", 1);
完整更新示例
结合过滤条件(比如按OrderId定位文档)执行原子更新:
// 构建过滤条件:找到指定OrderId的文档 var filter = Builders<OrderDetails>.Filter.Eq(x => x.OrderId, targetOrderId); // 构建更新操作:递增指定用户的浏览量,无此键则自动创建并设为1 var update = Builders<OrderDetails>.Update.Inc(x => x.TotalViewsPerUser[userId], 1); // 执行更新(IsUpsert设为false,因为我们只更新已存在的订单详情) var result = await mongoCollection.UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = false });
关键说明
MongoDB的Inc操作是原子性的,完全满足并发场景下的需求:
- 如果字典中已存在该用户ID的键,对应值会自动+1
- 如果不存在该键,会自动创建此键并将值设为1(因为增量是1)
内容的提问来源于stack exchange,提问作者Carlos Rodrigues
相关产品推荐
相关产品推荐

