我想插入一个带有默认值的新文档作为数组的一部分,或者如果文档已经存在则更新数组的那部分。
我的想法是:
db.test.update(
{ "a": 5 },
{ $setOnInsert: { "b": [0, 0] }, $min: { "b.0": 5 } },
{ upsert: true }
);
如果我这样做,那么我得到:
无法同时更新'b'和'b.0'
另一个想法是删除$setOnInsert
并保留$min
,因为在5
之间的最小值应为5
。
db.test.update(
{ "a": 5 },
{ $min: { "b.0": 5 } },
{ upsert: true }
);
这不会引发错误,但现在我收到的文件是:
{ "a" : 5, "b" : { "0" : 5 } }
我需要一个5
位于0
位置的数组,但不是具有0
属性的对象。
我怎样才能做到这一点?
答案 0 :(得分:1)
你可以使用.bulkWrite()
来实现这一点,它实际上是一个主要用例,说明为什么存在这种情况。它只向服务器发送“一个”实际请求,并且只有一个响应。它仍然是两个操作,但它们或多或少地捆绑在一起并且通常是原子的:
db.junk.bulkWrite([
{ "updateOne": {
"filter": { "a": 1 },
"update": { "$setOnInsert": { "b": [ 5,0 ] } },
"upsert": true
}},
{ "updateOne": {
"filter": { "a": 1 },
"update": { "$min": { "b.0": 5 } }
}}
])
第一次运行会给你一个“upsert”,注意它在响应中是“插入”而不是“修改”:
{
"acknowledged" : true,
"deletedCount" : 0,
"insertedCount" : 0,
"matchedCount" : 1,
"upsertedCount" : 1,
"insertedIds" : {
},
"upsertedIds" : {
"0" : ObjectId("5947c412d6eb0b7d6ac37f09")
}
}
当然,文件看起来像是:
{
"_id" : ObjectId("5947c412d6eb0b7d6ac37f09"),
"a" : 1,
"b" : [
5,
0
]
}
然后在实际案例中使用与$min
不同的值运行:
db.junk.bulkWrite([
{ "updateOne": {
"filter": { "a": 1 },
"update": { "$setOnInsert": { "b": [ 5,0 ] } },
"upsert": true
}},
{ "updateOne": {
"filter": { "a": 1 },
"update": { "$min": { "b.0": 3 } }
}}
])
回复:
{
"acknowledged" : true,
"deletedCount" : 0,
"insertedCount" : 0,
"matchedCount" : 2,
"upsertedCount" : 0,
"insertedIds" : {
},
"upsertedIds" : {
}
}
哪个“匹配”2
但当然$setOnInsert
不适用,结果是:
{
"_id" : ObjectId("5947c412d6eb0b7d6ac37f09"),
"a" : 1,
"b" : [
3,
0
]
}
就像它应该是