{
_id:'1',
name:'apple',
option:[{
weight:'10',
size:'40'
price:'40',
},
{weight:'40',
size:'40'
price:'200'}]
}
如果重量或大小不同我想要插入新的对象在数组中,如果大小和重量匹配我想更新它。我该怎么做?插入数组,其中元素不存在其他更新它(具有多个条件)
{
_id:'1',
name:'apple',
option:[{
weight:'10',
size:'40'
price:'40',
},
{weight:'40',
size:'40'
price:'200'}]
}
如果重量或大小不同我想要插入新的对象在数组中,如果大小和重量匹配我想更新它。我该怎么做?插入数组,其中元素不存在其他更新它(具有多个条件)
到your previous question类似,您使用.bulkWrite()
但由于数组元素的选择具有“多重条件”这是你使用$elemMatch
:
db.collection.bulkWrite([
{ "updateOne": {
"filter": {
"_id": "1",
"option": {
"$elemMatch": { weight": "40", "size": "40" }
}
},
"update": {
"$set": { "option.$.price": "300" }
}
}},
{ "updateOne": {
"filter": {
"_id": "1",
"option": {
"$not": {
"$elemMatch": { weight": "40", "size": "40" }
}
}
},
"update": {
"$push": { "option": { "weight": "40", "size": "40", "price": "300" } }
}
}},
{ "updateOne": {
"filter": { "_id": 1 },
"update": {
"$setOnInsert": {
"option": [
{ "weight": "40", "size": "40", "price": "300" }
]
}
},
"upsert": true
}}
])
所以操作是:
测试是存在$elemMatch
中的数组元素匹配条件,然后是$set
匹配值。
测试数组元素是否为$not
否定。您可以在每个属性上交替使用$ne
,但是否定两个匹配都比较干净的情况。
"$elemMatch": { "weight": { "$ne": "40" }, "size": { "$ne": "40" } }
在任何速率你$push
新的数组,当一个不匹配所提供的标准中找到。
只有在未找到主文档_id
的情况下尝试“upsert”,并使用$setOnInsert
,以便如果找到该文档,此操作将不执行任何操作。
和以前一样,只有其中的一个实际上会写任何东西,尽管整批发送到服务器。
这实际上执行3操作,而不是1. –
@AgostonHorvath是的。但是这只是一个**请求。你不能在一个操作中完成这个任务,并且阅读整个文档并写回来只是出于许多原因。 –
当你有这种复杂性的文档,然后请求在那里做深刻的改变时,对我来说,这是一个红旗,你的实际需求是复杂的更新和验证。你不能在mongo中做到这一点,并且即使你这样做也确实如此(就像你在回答中所建议的那样),但后来维护/改变它是一种痛苦。通过在代码中进行更改和验证,您可以获得更好的控制和灵活性,并且代码更少,更易于理解,并具有更好的测试可能性。 –
你可能能够用单一的只有mongodb的操作连接东西,你可能通过添加'version'字段并使用乐观锁定(比如java + spring-data)谷歌@Version)。这将允许在持久之前对完整对象进行复杂的更改和验证。
当然,你的意思是“所有”数组项目意味着“重量”和“大小”。在你的快速复制/粘贴你没有显示。 –
是的,我的错误,我编辑它 – naruto