Как обновить строку даты в массиве до формата даты в MongoDB?

#javascript #mongodb #date #mongodb-query #isodate

#javascript #mongodb #Дата #mongodb-запрос #isodate

Вопрос:

Моя коллекция MongoDB выглядит следующим образом:

 [
  {
    "id": "myid",
    "field": {
      "total": 1,
      "subfield": [
        {
          "time": "2020-08-06T08:33:57.977 0530"
    
        },
        {
          "time": "2020-05-08T04:13:27.977 0530"
          
        }
      ]
    }
  },
  {
    "id": "myid2",
    "field": {
      "total": 1,
      "subfield": [
        {
          "time": "2020-07-31T10:15:50.184 0530"
        }
      ]
    }
  }
]
  

Мне нужно обновить все документы и преобразовать строку даты в поле, time доступном в subfield массиве, в формат даты ISO MongoDB.

У меня тысячи документов и сотни объектов в subfield массиве

Я знаю о агрегатной функции $todate и $convert . Но я не хочу использовать агрегацию, потому что,

  1. Чтобы использовать $todate or $convert , мне нужно размотать field.subfield массив, что опять же является дорогостоящей операцией.

  2. Я хочу обновить свой документ и сохранить его в формате даты.

Версия моего сервера MongoDB: 4.0.3

Я попробовал следующее, но, похоже, это не работает, а также не возвращает никаких ошибок.

 db.collection.find().forEach(function(doc) { 
doc.field.subfield.time=new ISODate(doc.field.subfield.time);
db.collection.save(doc); 
})
  

Комментарии:

1. Платформа агрегации поддерживает обновления с помощью $ merge.

2. Спасибо, что указали. Но это доступно только с версии 4.2. Моя версия 4.0 @D.SM

3. Это всего лишь одноразовая операция?

4. да @WernfriedDomscheit

5. Если у вас тысячи документов, это не должно быть проблемой. В случае миллионов документов, которые могут вас беспокоить

Ответ №1:

Вы пропустили цикл для subfield , потому что это массив,

 db.collection.find().forEach(function(doc) { 
    doc.field.subfield.forEach(function(r) {
        r.time = new ISODate(r.time);
    })
    db.collection.save(doc); 
})
  

Если это на один раз, то время не имеет значения, я думаю, что оба варианта займут одинаковое время, если вы выполняете агрегацию или forEach.


Если вы планируете обновить версию MongoDB, тогда сформируйте 4.2, вариант, который вы можете обновить с помощью updateMany() использования конвейера обновления с агрегацией,

 db.collection.updateMany({},
    [{
        $set: {
            "field.subfield": {
                $map: {
                    input: "$field.subfield",
                    as: "r",
                    in: {
                        $mergeObjects: [
                            "$$r",
                            { time: { $toDate: "$$r.time" } }
                        ]
                    }
                }
            }
        }
    }]
)