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

MongoDB .NET Driver:如何递增双层嵌套字段?

问题描述

需求:递增MongoDB实体中带有指定标识符的双层嵌套字段amount。以下是competition_dota2的文档示例:

{
    "id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
    "type" : "COMPETITION_TYPE_ESPORTDOTA2",
    "status_type" : "COMPETITION_STATUS_TYPE_WAITING",
    "start_time" : 
    {
        "seconds": "60",
         "nanos": 928852400
    },
    "coefficient_groups" : 
    [
        {
            "id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
            "name" : "winner",
            "type" : "OUTCOME_GROUP_TYPE_ONE_WINNER",
            "coefficients" : 
            [
                    {
                        "id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
                        "description" : "team1 won",
                        "rate" : 1.2,
                        "status_type" : "COEFFICIENT_STATUS_TYPE_ACTIVE",
                        "amount" : 0,
                        "probability" : 50
                    },
                    {
                        "id" : "3c203bd7-2d7e-4937-a82a-e451cedf2ba8",
                        "description" : "team2 won",
                        "rate" : 0,
                        "status_type" : "COEFFICIENT_STATUS_TYPE_ACTIVE",
                        "amount" : 0,
                        "probability" : 50
                    }
            ]
        }
    ],
    "team1_id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
    "team2_id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
    "team1_kill_amount" : 0,
    "team2_kill_amount" : 0,
    "total_time" : 
    {
        "seconds": "60",
         "nanos": 928852400
    }
}

我尝试用以下C#代码递增amount字段,但仅针对顶层模型CompetitionDota2Entity创建了查询选项,请问这样的实现是否可行?

var competitionIdstring = competitionId.ToString();
var сoefficientIdstring = сoefficientId.ToString();

var filterBuilder = Builders<CompetitionDota2Entity>.Filter;
var updateBuilder = Builders<CompetitionDota2Entity>.Update;

var filterCompetitionId = filterBuilder.Eq(x => x.Id, competitionId.ToString());

var update = Builders<CompetitionDota2Entity>.Update;
var incAmount = update.Inc(
    "CompetitionDota2Entity.CoefficientGroups.$.Coefficients.$.Amount",
    amount);

var existingCoefficientGroup = await _collection.FindOneAndUpdateAsync(
                    filterCompetitionId,
                    incAmount,
                    _defaultCompetitionDota2EntityFindOption,
                    token);
解答

你的实现不可行,存在两个核心问题:

1. 更新路径错误

MongoDB的更新路径不需要包含实体类名称CompetitionDota2Entity,应该直接使用文档中的嵌套字段路径(匹配JSON里的蛇形命名,或对应实体类映射到MongoDB的字段名)。正确的路径应该是"coefficient_groups.$.coefficients.$.amount"(对应JSON文档字段),如果你的C#实体类用驼峰命名且MongoDB驱动配置了自动映射,也可以用"CoefficientGroups.$.Coefficients.$.Amount",但绝对不能加实体类前缀。

2. 缺少嵌套数组的过滤条件

MongoDB的$占位符用于匹配数组中第一个符合过滤条件的元素,但你当前的filter只指定了顶层的competition id,没有匹配目标coefficient_group和coefficient的id,导致MongoDB无法定位到需要更新的嵌套元素。

修正后的代码

var competitionIdStr = competitionId.ToString();
var coefficientIdStr = сoefficientId.ToString();
// 假设你有目标coefficient_group的id变量,比如coefficientGroupId
var coefficientGroupIdStr = coefficientGroupId.ToString();

var filterBuilder = Builders<CompetitionDota2Entity>.Filter;
// 同时匹配competition id、目标coefficient_group的id、目标coefficient的id
var filter = filterBuilder.And(
    filterBuilder.Eq(x => x.Id, competitionIdStr),
    filterBuilder.ElemMatch(x => x.CoefficientGroups, cg => cg.Id == coefficientGroupIdStr),
    filterBuilder.ElemMatch(x => x.CoefficientGroups[-1].Coefficients, c => c.Id == coefficientIdStr)
);

var updateBuilder = Builders<CompetitionDota2Entity>.Update;
// 使用正确的嵌套路径,去掉实体类名
var incAmount = updateBuilder.Inc("CoefficientGroups.$.Coefficients.$.Amount", amount);

var existingCoefficientGroup = await _collection.FindOneAndUpdateAsync(
    filter,
    incAmount,
    _defaultCompetitionDota2EntityFindOption,
    token);

关键说明

  • 用ElemMatch分别匹配coefficient_groups和coefficients数组中的目标元素,确保$占位符能精准定位到需要更新的嵌套对象。
  • 更新路径直接使用实体类的属性名即可,MongoDB驱动会自动处理与JSON字段名的映射(若配置了驼峰转蛇形规则)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:15:38