MongoDB .NET Driver:如何向嵌套数组中添加元素
向MongoDB嵌套多层数组插入元素的问题
我要实现向嵌套多层的数组中插入元素的功能,目标数组路径为RequestMessageLog.BiDirectionalMessageLogs.RequestMessageLog.ResponseMessageLog.ResponseMessageActionLogs,对应的文档结构如下:
{ "_id": "63206e8cc876d082460e33c3", "MessageTrackingId": "08eab450-a2bd-408a-afab-be9ea665503e", "RequestMessageLog": { "ResponseMessageLog": { "LogDateTime": "2022-09-13T11:50:36.426Z" }, "LogDateTime": "2022-09-13T11:50:36.333Z", "StatusCode": "Success", "BiDirectionalMessageLogs": [ { "MessageTrackingId": "bb7b5573-15ae-4db9-a67e-6862f31b9437", "RequestMessageLog": { "ResponseMessageLog": { "ResponseMessageActionLogs": [ { "LogDateTime": "2022-09-13T11:53:42.478Z", "Contents": "something" } ], "LogDateTime": "2022-09-13T11:53:42.477Z" }, "LogDateTime": "2022-09-13T11:53:42.477Z", "StatusCode": "Success", "BiDirectionalMessageLogs": null } } ] } }
尝试的解决方案及问题
方法1:使用Builders构建Filter和Update
FilterDefinition<MessageLog> filter = Builders<MessageLog>.Filter.Eq(e => e.MessageTrackingId, "08eab450-a2bd-408a-afab-be9ea665503e"); filter &= Builders<MessageLog>.Filter.Eq("RequestMessageLog.BiDirectionalMessageLogs.MessageTrackingId", "bb7b5573-15ae-4db9-a67e-6862f31b9437"); UpdateDefinition<MessageLog> update = Builders<MessageLog>.Update.Push("RequestMessageLog.BiDirectionalMessageLogs.RequestMessageLog.ResponseMessageLog.$.ResponseMessageActionLogs", responseMessageActionLog);
执行后报错:
A write operation resulted in an error. WriteError: { Category : "Uncategorized", Code : 28, Message : "Cannot create field 'RequestMessageLog' in element {BiDirectionalMessageLogs:[ { MessageTrackingId: "bb7b5573....`
方法2:使用JsonCommand执行更新
IMongoDatabase Database = client.GetDatabase("Logs"); var cmd = new JsonCommand<BsonDocument>(@"Database.MessageLog.update( {'MessageTrackingId' : '08eab450-a2bd-408a-afab-be9ea665503e', 'RequestMessageLog.BiDirectionalMessageLogs.MessageTrackingId': '4dc1f99c-b465-4170-9fef-c78cf5e92216'}, {$push:{'RequestMessageLog.BiDirectionalMessageLogs.RequestMessageLog.ResponseMessageLog.$.ResponseMessageActionLogs':{'LogDateTime':'2022-09-13T11:53:42.478Z', 'Contents':'something'}}})"); Database.RunCommand(cmd);
我也参考过关于Mongo数组嵌套插入的帖子,但没法在C#中实现。请问我哪里操作有误?
问题原因及正确实现
你的核心错误是数组位置操作符$的使用位置错误。$只会匹配筛选条件中第一个命中的数组元素,你之前把$放在了ResponseMessageLog后,导致MongoDB误解了更新路径,试图在BiDirectionalMessageLogs数组元素下创建新的RequestMessageLog字段,这和现有文档结构冲突,因此抛出错误。
正确的Builders实现方式
var filter = Builders<MessageLog>.Filter.And( Builders<MessageLog>.Filter.Eq(e => e.MessageTrackingId, "08eab450-a2bd-408a-afab-be9ea665503e"), Builders<MessageLog>.Filter.Eq("RequestMessageLog.BiDirectionalMessageLogs.MessageTrackingId", "bb7b5573-15ae-4db9-a67e-6862f31b9437") ); var update = Builders<MessageLog>.Update.Push( "RequestMessageLog.BiDirectionalMessageLogs.$.RequestMessageLog.ResponseMessageLog.ResponseMessageActionLogs", responseMessageActionLog ); // 执行更新 var collection = Database.GetCollection<MessageLog>("MessageLog"); var result = collection.UpdateOne(filter, update);
正确的JsonCommand实现方式
同时修正$的位置和命令中的数据库引用错误:
IMongoDatabase Database = client.GetDatabase("Logs"); var cmd = new JsonCommand<BsonDocument>(@"db.MessageLog.update( {'MessageTrackingId' : '08eab450-a2bd-408a-afab-be9ea665503e', 'RequestMessageLog.BiDirectionalMessageLogs.MessageTrackingId': 'bb7b5573-15ae-4db9-a67e-6862f31b9437'}, {$push:{'RequestMessageLog.BiDirectionalMessageLogs.$.RequestMessageLog.ResponseMessageLog.ResponseMessageActionLogs':{'LogDateTime':'2022-09-13T11:53:42.478Z', 'Contents':'something'}}} )"); Database.RunCommand(cmd);
关键说明
- 将
$移到BiDirectionalMessageLogs之后,MongoDB会定位到筛选条件匹配的那个数组元素,再在该元素内部的目标数组执行push操作。 - JsonCommand中需使用
db.MessageLog而非Database.MessageLog,这是你之前的另一个小错误。
内容的提问来源于stack exchange,提问作者Muhammad Hamza
相关产品推荐
相关产品推荐

