Самый эффективный способ поместить поля внедренного документа в его родительский для всей коллекции MongoDB? - PullRequest
1 голос
/ 15 мая 2019

Я ищу наиболее эффективный способ изменить все документы коллекции из этой структуры:

{
  [...]
  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 Ответ

1 голос
/ 15 мая 2019

Вы можете рассмотреть возможность использования $ out в качестве альтернативного решения для одной команды.Его можно использовать для замены существующей коллекции на вывод агрегации.Зная, что вы можете написать следующий конвейер агрегации:

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

$ replaceRoot позволяет вам продвигать объект, который объединяет старые $$ROOT и myValues в корневой уровень.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...