对于整个MongoDB集合,将嵌入式文档的字段放在其父级中最有效的方法是?

时间:2019-05-14 21:41:56

标签: mongodb mongodb-query

我正在寻找最有效的方法来从此结构修改集合的所有文档:

{
  [...]
  myValues:
  {
     a: "any",
     b: "content",
     c: "can be found here"
  }
  [...]
}

所以变成这样:

{
   [...]
   a: "any",
   b: "content",
   c: "can be found here"
   [...]
}

基本上,我希望将myValues字段下的所有内容都放入集合的所有文档的父文档中。

我一直在寻找一种使用dbCollection.updateMany()在单个查询中执行此操作的方法,除非似乎myValues的内容对于所有文档都相同,否则似乎不可能做到这一点。 。但是在我的情况下,myValues的内容从一个文档更改为另一个文档。例如,我尝试过:

db.getCollection('myCollection').updateMany({ myValues: { $exists: true } }, { $set: '$myValues' });

认为它可能会解决myValues对象,并使用该对象在文档中进行设置。但是它返回一个错误,指出将字符串分配给$set字段是非法的。

那么,对于我想做的事情,最有效的方法是什么?是否可以通过一个命令来更新集合中的所有文档?

还是我需要遍历集合的每个文档,并逐个更新它们?

目前,我使用以下代码遍历所有文档:

var documents = await myCollection.find({ myValues: { $exists: true } });
for (var document = await documents.next(); document != null; document = await documents.next())
{
    await myCollection.updateOne({ _id: document._id }, { $set: document.myValues, $unset: { myValues: 1} });
}

由于我的收藏很大,因此执行起来会花费很长时间。

1 个答案:

答案 0 :(得分:1)

您可以考虑使用$out作为替代的单命令解决方案。它可用于将现有集合替换为聚合的输出。知道您可以编写以下聚合管道:

db.myCollection.aggregate([
    {
        $replaceRoot: {
            newRoot: {
                $mergeObjects: [ "$$ROOT", "$myValues" ]
            }
        }
    },
    {
        $project: {
            myValues: 0
        }
    },
    {
        $out: "myCollection"
    }
])

$replaceRoot使您可以升级将旧的$$ROOTmyValues合并到根级别的对象。