猿问

新手上路,Mongodb update操作更新二维数组有趣的现象各位有什么建议?

问题描述
有如下数据:
{"_id":1,"name":"dave123","favorites":["chocolate","cake","butter","apples"]}
{"_id":2,"name":"li","favorites":["apples","pudding","pie","cake"]}
{"_id":3,"name":"ahn","favorites":["pears","pecans","chocolate","cherries"]}
{"_id":4,"name":"ty","favorites":["icecream"]}
然后我刚才操作失误,原本想给数组中添加一个元素结果给添加了一个数组进去:
db.test.update({_id:2},{$push:{favorites:['cake']}})
执行后的数据如下:
{"_id":1,"name":"dave123","favorites":["chocolate","cake","butter","apples"]}
{"_id":2,"name":"li","favorites":["apples","pudding","pie","cake",["cake"]]}
{"_id":3,"name":"ahn","favorites":["pears","pecans","chocolate","cherries"]}
可以看到id2的文档的favorites字段中又包含了一个数组
想法设法删除掉这个数组
我知道$pull命令可以删除掉数组中的一个元素,但是它需要一个条件,于是问题被引到了如何在数组中查询另外一个数组.
命令如下:
db.tester.find({favorites:{$in:[['cake']]}})
输出:
{"_id":2,"name":"li","favorites":["apples","pudding","pie","cake",["cake"]]}
然后我尝试使用update来完成这个操作,由于集合中就这么一条特殊数据我就没有指定条件:
db.tester.update({},{$pull:{favorites:{$in:[['cake']]}}})
输出:
WriteResult({"nMatched":1,"nUpserted":0,"nModified":0})
喜闻乐见,匹配到了东西但是没有更新东西.
继续折腾
在我的努力下试出来了这么一个命令:
db.tester.update({favorites:{$in:[['cake']]}},{$pull:{favorites:{$in:[['cake']]}}})
输出:
WriteResult({"nMatched":1,"nUpserted":0,"nModified":1})
这次这个数组中的元素被正确的删除掉了.
最终的问题
WHY?
udpate操作中查询和跟随着的修改操作有什么潜在的关系吗,还是和$pull中的条件有关系?
慕虎7371278
浏览 255回答 2
2回答

宝慕林4294392

答案就像我猜的一样,是一个细节问题.Bydefault,theupdate()methodupdatesasingledocument.默认情况下update只会修改匹配到的第一条数据.在我使用的语句中:db.tester.update({},{$pull:{favorites:{$in:[['cake']]}}})这条命令会匹配多条数据,鉴于上面提到的规则MongoDB匹配到了多个数据后实际交由$pull操作的只有第一条:{"_id":1,"name":"dave123","favorites":["chocolate","cake","butter","apples"]}也就是上面这条,但是$pull条件却不成立了,所以不会进行任何更新.这也解释了为什么如下的操作可行:db.test.update({favorites:{$in:[['cake']]}},{$pull:{favorites:{$in:[['cake']]}}})查询只会匹配到第一条数据而这条数据则会交由$pull处理.如何解决问题很简单在这个情况下开启多条修改支持就可以了,命令如下:db.tester.update({},{$pull:{favorites:{$in:[['cake']]}}},{multi:true})这样一来查询到的四条数据都会将由后面的更新处理而$pull也会匹配到对应的内容.我是如何找到问题的观察我们的前两条数据:{"_id":1,"name":"dave123","favorites":["chocolate","cake","butter","apples"]}{"_id":2,"name":"li","favorites":["apples","pudding","pie","cake"]}我尝试删除两者数组中都存在的cake元素:db.test.update({},{$pull:{favorites:{$in:['cake']}}})但是只会删除第一条,第二条数据会进行匹配但是不会删除.

萧十郎

rs0:PRIMARY>db.test.insert({"_id":2,"name":"li","favorites":["apples","pudding","pie","cake",["cake"]]})rs0:PRIMARY>db.test.update({},{$pull:{favorites:{$in:[['cake']]}}})WriteResult({"nMatched":1,"nUpserted":0,"nModified":1})rs0:PRIMARY>db.test.find(){"_id":2,"name":"li","favorites":["apples","pudding","pie","cake"]}看上去我并不能重现这个问题。你的版本是?
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答