MongoDB集合删除嵌套文档内_types数组字段失败求助
_types字段的问题 看起来你遇到的问题主要是数组字段的更新方式不对,再加上命令参数的写法有误,咱们一步步拆解清楚:
先分析你尝试的命令为什么无效:
第一个命令
db.test.update({}, {$unset: {"_types":1}}, multi=true)
这个命令是尝试移除根级的_types字段,但你的_types是嵌套在data_servers数组的子文档里,根本匹配不到目标字段,所以自然nModified:0。另外,在MongoDB 3.x及以上版本,update的第三个参数是options对象,你直接写multi=true会被当成upsert=true(旧版语法是update(query, update, upsert, multi)),这就是为什么你会看到nUpserted:1——它误插入了一个空文档,而非批量修改现有文档。第二个命令
db.test.update({}, {$unset: {"data_servers._types": ""}})
没加multi: true选项的话,默认只会修改第一个匹配的文档。更关键的是,直接用data_servers._types这种写法,在MongoDB 3.2之前无法批量更新数组中的所有子文档;即使是3.2+版本,也需要用数组通配符才能批量操作所有元素。第三个命令
db.test.update({}, {$unset: {"data_servers.$._types": ""}})$占位符是用来匹配数组中第一个符合查询条件的元素,但你的查询条件是空的{},没有指定任何数组元素的匹配规则,所以$无法正确定位要修改的子文档,自然无法生效。
正确的解决方案
如果你使用的是MongoDB 3.2及以上版本(推荐)
使用$[]数组通配符,它可以匹配数组中的所有元素,从而批量移除每个子文档里的_types字段:
// 批量修改所有文档,移除data_servers数组中每个子文档的_types字段 db.test.updateMany({}, {$unset: {"data_servers.$[]._types": ""}})
或者用传统的update命令配合options对象:
db.test.update({}, {$unset: {"data_servers.$[]._types": ""}}, {multi: true})
如果你的文档中同时存在根级的_types字段,可以一次性处理:
db.test.updateMany({}, {$unset: {"_types": "", "data_servers.$[]._types": ""}})
如果你使用的是MongoDB 3.2以下版本
需要遍历每个文档,手动处理数组中的每个元素:
db.test.find().forEach(function(doc) { // 遍历data_servers数组,移除每个子文档的_types字段 doc.data_servers.forEach(function(server) { delete server._types; }); // 保存修改后的文档 db.test.save(doc); });
这样就能确保所有嵌套在数组里的_types字段都被移除啦。
内容的提问来源于stack exchange,提问作者user3991409

