MongoDB嵌套数组更新报错:Update document requires atomic operators排查
问题描述
开发持久化层更新答案选项时,C#驱动执行正常,但将日志中的查询语句放到3T Studio执行时,出现MongoInvalidArgumentError错误,提示"Update document requires atomic operators"。
相关代码与数据结构
C#驱动代码
public async Task Update(ItemList list, Guid id, Option option, CancellationToken cancellationToken = default) { var filter = Builders<ItemList>.Filter.And( Builders<ItemList>.Filter.Eq("_id", list.Id), Builders<ItemList>.Filter.Eq("Items._id", id) ); var update = Builders<ItemList>.Update.Set("Items.$[i].Options.$[j]", option); var arrayFilters = new List<ArrayFilterDefinition<ItemList>> { new BsonDocumentArrayFilterDefinition<ItemList>( new BsonDocument("i._id", elementId) ), new BsonDocumentArrayFilterDefinition<ItemList>( new BsonDocument("j._id", option.Id) ) }; var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters }; await _collection.UpdateOneAsync(filter, update, updateOptions, cancellationToken); }
数据库存储结构
{ "_id": "ae39e133-18a6-43b0-8745-b13a00dd8632", "ItemId": "af21eeb1-e952-4e10-af59-b13800cf8880", "Items": [ { "_t": "Item", "_id": "e42f593e-1444-4f3a-9991-b15d008d9a99", "Options": [ { "_id": "7dcccc2e-949a-4743-bd53-b15d008d9aa5", "Label": "test", "Value": "a4e1c768-6cf9-417d-82bd-275c92be6a91" } ] } ] }
3T Studio中执行的报错语句
db.getCollection("Defintion").updateOne( { "update" : "Defintion", "ordered" : true, "$db" : "dbName", "lsid" : { "id" : CSUUID("28fd5c50-4d0b-4a71-a2d4-d6c598b6f413") }, "updates" : [{ "q" : { "_id" : "ae39e133-18a6-43b0-8745-b13a00dd8632", "Items._id" : "e42f593e-1444-4f3a-9991-b15d008d9a99" }, "u" : { "$set" : { "Items.$[i].Options.$[j]" : { "_id" : "7dcccc2e-949a-4743-bd53-b15d008d9aa5", "Label" : "Test2", "Value" : "a4e1c768-6cf9-417d-82bd-275c92be6a91"} } }, "arrayFilters" : [{ "i._id" : CSUUID("e42f593e-1444-4f3a-9991-b15d008d9a99") }, { "j._id" : CSUUID("7dcccc2e-949a-4743-bd53-b15d008d9aa5") }] }] } )
解决方法
错误原因是你直接把MongoDB驱动的命令协议格式当成了updateOne的参数传入,而updateOne的语法要求第一个参数是过滤条件,第二个是更新操作,第三个是可选配置。
修正后的正确语句应该是:
db.getCollection("Defintion").updateOne( // 过滤条件 { "_id" : "ae39e133-18a6-43b0-8745-b13a00dd8632", "Items._id" : "e42f593e-1444-4f3a-9991-b15d008d9a99" }, // 更新操作 { "$set" : { "Items.$[i].Options.$[j]" : { "_id" : "7dcccc2e-949a-4743-bd53-b15d008d9aa5", "Label" : "Test2", "Value" : "a4e1c768-6cf9-417d-82bd-275c92be6a91"} } }, // 配置项(包含数组过滤器) { arrayFilters: [ { "i._id" : CSUUID("e42f593e-1444-4f3a-9991-b15d008d9a99") }, { "j._id" : CSUUID("7dcccc2e-949a-4743-bd53-b15d008d9aa5") } ] } )
另外注意C#代码里的小问题:arrayFilters中使用的elementId变量未在方法参数中定义,应替换为传入的id参数,避免运行时出错:
new BsonDocumentArrayFilterDefinition<ItemList>( new BsonDocument("i._id", id) // 替换elementId为id )
内容的提问来源于stack exchange,提问作者Heis
相关产品推荐
相关产品推荐

