Оболочка MongoDB: присоединить одно поле из другой коллекции

#mongodb

#mongodb

Вопрос:

У меня есть коллекция Spots:

 - spotId
- name
  

и коды:

 - codeId
- spotId
- code
  

Я хочу представить поле

 - spotName
  

к кодам (и присоедините по spotId).

Как мне обновить все мои существующие документы в оболочке mongo?

Когда я пытаюсь использовать $ lookup, я всегда получаю весь документ Spot, а не только поле name.

Ответ №1:

Если вы хотите получить формат, в котором вы получаете spotName в каждом документе, вы можете использовать конвейер агрегации. $lookup было хорошим началом. Здесь он генерирует полный массив, который вы можете $unwind и спроецировать необходимый материал

 [{$lookup: {
        from: 'Spots',
        localField: 'spotId',
        foreignField: 'spotId',
        as: 'new_field'
    }},
{$unwind: '$new_field'},
{$project: {
    codeId: 1,
    spotId: 1,
    code: 1,
    spotName: '$new_field.name'
 }}

]
  

Приведенное выше решение представляет случай, если вам нужно просто использовать результаты.

Если вы действительно хотите выполнить update для коллекции, единственным способом было бы написать find , который просматривает все документы в кодах, а затем, как только он получает документ, выполняет поиск документа в Spots с помощью findOne , а затем выдает инструкцию update .

 Codes.find().each(function(err, doc) {
  Spots.findOne({spotId: doc.spotId}, function (err, item) {
    Codes.update({codeId: doc.codeId}, {$set: {spotName: item.name}}, function (err, res) {})
  })
});
  

Ответ №2:

Вам нужно будет запустить скрипт

 var spotMap ={}; Spots.find({},{spotId:1,name:1}).each(function(spot){spotMap[spot.spotId]=spot.name}); Codes.find({}).each(function(code){code.spotName=spotMap[code.spotId]; db.Codes.save(code);});
  

Также обратите внимание, что если коллекция слишком большая, возникнут проблемы при извлечении всех данных сразу из-за ограничения mongo на 16 МБ данных в памяти, и тогда вам придется запускать скрипт пакетами несколько раз.

 Codes.find({}).limit(1000).each(function(code){//do normal stuff}

Codes.find({}).skip(1000).limit(1000).each(function(code){//do normal stuff}

Codes.find({}).skip(2000).limit(1000).each(function(code){//do normal stuff}
  

и так далее….