2017-10-18 76 views
2
{ 
_id:'1', 
name:'apple', 
option:[{ 
weight:'10', 
size:'40' 
price:'40', 
}, 
{weight:'40', 
size:'40' 
price:'200'}] 
} 

如果重量或大小不同我想要插入新的对象在数组中,如果大小和重量匹配我想更新它。我该怎么做?插入数组,其中元素不存在其他更新它(具有多个条件)

+0

当然,你的意思是“所有”数组项目意味着“重量”和“大小”。在你的快速复制/粘贴你没有显示。 –

+0

是的,我的错误,我编辑它 – naruto

回答

1

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 
    }} 
]) 

所以操作是:

  1. 测试是存在$elemMatch中的数组元素匹配条件,然后是$set匹配值。

  2. 测试数组元素是否为$not否定。您可以在每个属性上交替使用$ne,但是否定两个匹配都比较干净的情况。

    "$elemMatch": { "weight": { "$ne": "40" }, "size": { "$ne": "40" } } 
    

    在任何速率你$push新的数组,当一个匹配所提供的标准中找到。

  3. 只有在未找到主文档_id的情况下尝试“upsert”,并使用$setOnInsert,以便如果找到该文档,此操作将不执行任何操作。

和以前一样,只有其中的一个实际上会写任何东西,尽管整批发送到服务器。

+0

这实际上执行3操作,而不是1. –

+0

@AgostonHorvath是的。但是这只是一个**请求。你不能在一个操作中完成这个任务,并且阅读整个文档并写回来只是出于许多原因。 –

+0

当你有这种复杂性的文档,然后请求在那里做深刻的改变时,对我来说,这是一个红旗,你的实际需求是复杂的更新和验证。你不能在mongo中做到这一点,并且即使你这样做也确实如此(就像你在回答中所建议的那样),但后来维护/改变它是一种痛苦。通过在代码中进行更改和验证,您可以获得更好的控制和灵活性,并且代码更少,更易于理解,并具有更好的测试可能性。 –

0

你可能能够用单一的只有mongodb的操作连接东西,你可能通过添加'version'字段并使用乐观锁定(比如java + spring-data)谷歌@Version)。这将允许在持久之前对完整对象进行复杂的更改和验证。

相关问题