MongoDB .NET:在ArrayFilter中通过ID更新子文档

编程语言 2026-07-10

目标是使用目标子文档的ID来更新一个子文档——使用一个 ArrayFilter

我理解有多种方式可以完成这次数据更新。 但出于学习目的,想使用 ArrayFilter。 此更新使用玩家文档的ID,将 PlayerName 替换为 "Josh"。

注:作为一个合理性检查,如果把 BsonDocumentArrayFilterDefinition 改为基于 PlayerName 进行匹配,而不是按ID,则更新就会成功。

样本文档(已裁剪):

db.Teams.find()
[
  {
    _id: ObjectId('000000000000000000002000'),
    TeamName: 'GoldDiggers',
    Players: [
      {
        _id: ObjectId('000000000000000000002001'),
        PlayerName: 'Gary',
      },
      {
        _id: ObjectId('000000000000000000002002'),
        PlayerName: 'Greg',
      },
    ]
  }
]

下面的MONGOSH命令执行成功,将 PlayerName 的值从 "Gary" 改为 "Josh"。

db.Teams.updateOne(
  { _id: new ObjectId("000000000000000000002000") },
  { $set: { "Players.$[myIdentifier1].PlayerName": "Josh" } },
  {
    arrayFilters: 
    [     
      {"myIdentifier1._id": { $eq: new ObjectId("000000000000000000002001") }}
    ]
  }
)

尝试使用一个 ArrayFilter 做同样更新的C#代码:

string myIdentifier1 = "firstIdentifier";
var filterTeam = Builders<Team>.Filter.Eq("Id", "000000000000000000002000");
var updateUsingArrayFilter = Builders<Team>.Update.Set($"Players.$[{myIdentifier1}].PlayerName", "Josh");

var arrayFilter1 = new BsonDocumentArrayFilterDefinition<BsonDocument>
(
    // new BsonDocument($"{myIdentifier1}.PlayerName", new BsonDocument("$eq", "Gary"))  // Sanity check - using PlayerName instead of ID => successful update
    // new BsonDocument($"{myIdentifier1}.Id", "000000000000000000002001")
    // new BsonDocument($"{myIdentifier1}._id", "000000000000000000002001")
    // new BsonDocument($"{myIdentifier1}.Id", new BsonDocument("$eq", "000000000000000000002001"))
    new BsonDocument($"{myIdentifier1}._id", new BsonDocument("$eq", "000000000000000000002001"))
);

arrayFilters = new List<ArrayFilterDefinition> { arrayFilter1 };

updateOptions = new UpdateOptions
{
    ArrayFilters = arrayFilters
};
var result = collection.UpdateOne(filterTeam, updateUsingArrayFilter, updateOptions);

上方被注释掉的几行是不同的用法尝试,匹配子文档的ID。以下是这四次尝试所记录的日志。

Command started update UpdateSubDocumentTesting { "update" : "Teams", "ordered" : true, "$db" : "UpdateSubDocumentTesting", "lsid" : { "id" : { "$binary" : { "base64" : "tFsUYfi2SLyLv1vi3JF6eg==", "subType" : "04" } } }, "updates" : [{ "q" : { "_id" : { "$oid" : "000000000000000000002000" } }, 
"u" : { "$set" : { "Players.$[firstIdentifier].PlayerName" : "Josh" } }, 
"arrayFilters" : [{ "firstIdentifier.Id" : "000000000000000000002001" }] }] }

Command started update UpdateSubDocumentTesting { "update" : "Teams", "ordered" : true, "$db" : "UpdateSubDocumentTesting", "lsid" : { "id" : { "$binary" : { "base64" : "siFCYB15RiOsqa3zB3FFSg==", "subType" : "04" } } }, "updates" : [{ "q" : { "_id" : { "$oid" : "000000000000000000002000" } }, 
"u" : { "$set" : { "Players.$[firstIdentifier].PlayerName" : "Josh" } }, 
"arrayFilters" : [{ "firstIdentifier._id" : "000000000000000000002001" }] }] }

Command started update UpdateSubDocumentTesting { "update" : "Teams", "ordered" : true, "$db" : "UpdateSubDocumentTesting", "lsid" : { "id" : { "$binary" : { "base64" : "1MjYpIlTTJGzBLQD0oa/bQ==", "subType" : "04" } } }, "updates" : [{ "q" : { "_id" : { "$oid" : "000000000000000000002000" } }, 
"u" : { "$set" : { "Players.$[firstIdentifier].PlayerName" : "Josh" } }, 
"arrayFilters" : [{ "firstIdentifier.Id" : { "$eq" : "000000000000000000002001" } }] }] }

Command started update UpdateSubDocumentTesting { "update" : "Teams", "ordered" : true, "$db" : "UpdateSubDocumentTesting", "lsid" : { "id" : { "$binary" : { "base64" : "9/5IuiFsTP6bgcLQaF5lqw==", "subType" : "04" } } }, "updates" : [{ "q" : { "_id" : { "$oid" : "000000000000000000002000" } }, 
"u" : { "$set" : { "Players.$[firstIdentifier].PlayerName" : "Josh" } }, 
"arrayFilters" : [{ "firstIdentifier._id" : { "$eq" : "000000000000000000002001" } }] }] }

所有更新尝试都返回了 "Command succeeded",但实际没有进行修改。

解决方案

确保在执行任何筛选时,所提供的筛选值的类型必须与文档中定义的属性类型相匹配。

所提供的文档显示,_idPlayers 数组中属于 ObjectId 类型。因此,你应该把值以 ObjectId 类型提供,而不是字符串类型,用于 arrayFilter1

var arrayFilter1 = new BsonDocumentArrayFilterDefinition<BsonDocument>(
    new BsonDocument($"{myIdentifier1}._id", 
        new BsonDocument("$eq", 
            ObjectId.Parse("000000000000000000002001")
        )
    )
);
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章