如何在mongo中构造查询来更新嵌套数组文档?

我在mongo有以下文件,

{ "_id" : ObjectId("506e9e54a4e8f51423679428"), "description" : "ffffffffffffffff", "menus" : [ { "_id" : ObjectId("506e9e5aa4e8f51423679429"), "description" : "ffffffffffffffffffff", "items" : [ { "name" : "xcvxc", "description" : "vxvxcvxc", "text" : "vxcvxcvx", "menuKey" : "0", "onSelect" : "1", "_id" : ObjectId("506e9f07a4e8f5142367942f") } , { "name" : "abcd", "description" : "qqq", "text" : "qqq", "menuKey" : "0", "onSelect" : "3", "_id" : ObjectId("507e9f07a4e8f5142367942f") } ] }, { "_id" : ObjectId("506e9e5aa4e8f51423679429"), "description" : "rrrrr", "items" : [ { "name" : "xcc", "description" : "vx", "text" : "vxc", "menuKey" : "0", "onSelect" : "2", "_id" : ObjectId("506e9f07a4e8f5142367942f") } ] } ] } 

现在,我想更新以下文档:

  { "name" : "abcd", "description" : "qqq", "text" : "qqq", "menuKey" : "0", "onSelect" : "3", "_id" : ObjectId("507e9f07a4e8f5142367942f") } 

我有主要的documnet id: _ id ”:ObjectId(“506e9e54a4e8f51423679428”)菜单id“_id”:ObjectId(“506e9e54a4e8f51423679428”)以及项目id “_id”:ObjectId(“507e9f07a4e8f5142367942f”) ,需要更新。

我试过使用以下查询:

db.collection.update({ "_id" : { "$oid" : "506e9e54a4e8f51423679428"} , "menus._id" : { "$oid" : "506e9e5aa4e8f51423679429"}},{ "$set" : { "menus.$.items" : { "_id" : { "$oid" : "506e9f07a4e8f5142367942f"}} , "menus.$.items.$.name" : "xcvxc66666", ...}},false,false);

但它不起作用……

位置运算符不会对您尝试使用它的级别数进行处理( https://jira.mongodb.org/browse/SERVER-831?focusedCommentId=22438&page=com.atlassian.jira.plugin.system .issuetabpanels%3Acomment-tabpanel )带menus.$.items.$.name ,即使它确实,MongoDB查询解析器也不知道其他$是什么来自updatefind

您需要从架构中提取项目,分别更新,然后更新根文档。

判断何时应该单独进行查询的一个好方法是认为每个菜单听起来像一个单独的实体(或关系数据库中的表),因此您可能应该分别更新这些实体(或关系模型中的表)父实体(表)。

首先,您将获得主根文档。 在客户端滚动它的菜单,然后$set特定菜单$set为您在客户端构建的整个项目。

编辑

我想象这个工作客户端的方式是(伪代码,因为我的Java有点生疏)首先以活动记录方式获取该文档:

 doc = db.col.find({ "_id" : { "$oid" : "506e9e54a4e8f51423679428"} , "menus._id" : { "$oid" : "506e9e5aa4e8f51423679429"}}); 

然后,您将遍历分配值的文档:

 foreach(doc.menus as menu_key => menu){ foreach(menu['items'] as key => item){ if(item._id == { "$oid" : "506e9f07a4e8f5142367942f"}){ doc.menus[menu_key][key][name] = "xcvxc66666" } } } 

然后在提交所有更改后简单保存文档:

 db.col.save(doc); 

这当然只是一种方式,这种方式使用我个人喜欢的activen记录范例。 在这个想法中,您可以将查找与您需要在文档上修改的所有其他内容相结合,在客户端构建它,然后将所有内容作为单个查询发送到您的数据库。