Мангуст найти один внутри цикла

1

У меня есть document Users с свойством storage определенным как массив ObjectId ссылается другой document под названием Storage. Я пытаюсь получить конкретного пользователя, а затем возвращать информацию о хранилищах внутри массива.

Это мой код:

module.exports.storageDetail = function(req, res) {
      User.findOne({'userId': req.user.userId}, 'storages').then(function(data){
        var storageArray = [];

        data.storages.forEach(function(record){
          Storage.findOne({_id: record}, function(err, storage){
            storageArray.push(storage);
          });
        });

        return Promise.all(storageArray);
      }).then(function(storageList){
        res.render('storage_template', {
          storage: storageList
        });
        console.log(storageList);
      });
}

Но после выполнения, storageList - пустой массив.

Я новичок в node.js и, пожалуйста, дайте мне знать, если мне нужно предоставить дополнительную информацию.

Теги:
mongoose

3 ответа

1
Лучший ответ

Итак, главное, что вам нужно .exec(), чтобы вернуть Promise. Вот почему ваша попытка не удалась. Но есть и синтаксически более сильные подходы.

Вместо этого используйте .map() и вызовите .exec() чтобы вернуть Promise

User.findOne({'userId': req.user.userId}, 'storages').then(function(data){
  var storageArray = data.storages.map(function(id) { 
    return Storage.findOne({_id: id }).exec() 
  });
  return Promise.all(storageArray);
}).then(function(storageList){
  res.render('storage_template', {
    storage: storageList
  });
  console.log(storageList);
});

Или вместо этого используйте $in с .find() где метод возвращает массив, и оператор позволяет указать массив вещей, которые должны соответствовать:

User.findOne({'userId': req.user.userId}, 'storages').then(function(data){
  return Storage.find({ "_id": { "$in": data.storages } }).exec();
}).then(function(storageList){
  res.render('storage_template', {
    storage: storageList
  });
  console.log(storageList);
});

Это также похоже на то, что вы могли бы просто использовать .populate()

User.findOne({'userId': req.user.userId}, 'storages')
  .populate('storages')
  .then(function(data) {
    res.render('storage_template', {
      storage: data.storages
    });
    console.log(data.storages);
  });

Но в вашем вопросе неясно, действительно ли они определены как ссылки на модель Storage или нет.

Также см. " Запросы не обещания" в документации для мангуста.

  • 0
    Оба решения работают отлично! Подскажите, пожалуйста, как мне использовать первый с ES5?
  • 0
    @Valip Я заменил синтаксис жирной стрелки на обычную функцию для вас. Главное здесь - это .exec() чтобы получить Обещание.
1

Если вы используете mongoose, вы можете использовать .populate() чтобы получить информацию о ваших storages из коллекции Storage.

можете попробовать это

module.exports.storageDetail = function(req, res) {
  User.findOne({'userId': req.user.userId}, 'storages')
    .populate('storages')
    .exec(function (err, storageList) {
      if (err) return handleError(err);
      console.log(storageList);
      res.render('storage_template', {
        storage: storageList
      });
    });
}

для использования этого .populate() убедитесь, что сначала в вашей модели User вы добавили ref для storages

лайк:

storages: [{ type: Schema.Types.ObjectId, ref: 'Storage' }]
0

//сделать npm установить lodash

const _ = require('lodash');
 module.exports.storageDetail = function(req, res) {
  User.findOne({'userId': req.user.userId}, 'storages').then(function(data){
    var storageArray = [];
    let queries =  _.map(data.storages, (record)=>{
     return Storage.findOne({_id: record}, function(err, storage){
        storageArray.push(storage);
      });
})

    return Promise.all(queries);
  }).then(function(storageList){
    res.render('storage_template', {
      storage: storageList
    });
    console.log(storageList);
  });
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню