Подтвердить что ты не робот

Mongoose: глубокое население (заполнение населенного поля)

У меня есть модель Category:

Category:
    ...
    articles: [{type:ObjectId, ref:'Article'}]

Модель статьи содержит ref для Account model.

Article:
    ...
    account: {type:ObjectId, ref:'Account'}

Итак, с заполненной моделью articles Category будет:

{ //category
    articles: //this field is populated
     [ { account: 52386c14fbb3e9ef28000001, // I want this field to be populated
         date: Fri Sep 20 2013 00:00:00 GMT+0400 (MSK),
         title: 'Article 1' } ],
    title: 'Category 1' }

Вопросы: как заполнить подполе (учетную запись) заполненного поля ([статьи])? Вот как я это делаю сейчас:

globals.models.Category
    .find
        issue : req.params.id
        null
        sort:
            order: 1
    .populate("articles") # this populates only article field, article.account is not populated
    .exec (err, categories) ->
        console.log categories

Я знаю, что это обсуждалось здесь: Mongoose: заполнить заполненное поле, но не найдено никакого реального решения

4b9b3361

Ответ 2

Во-первых, обновите Мангуста 3 до 4, а затем используйте самый простой способ для глубокой популяции в мангусте, как показано ниже:

Предположим, у вас есть схема блога, имеющая userId в качестве ref Id, а затем в User у вас есть некоторый отзыв в качестве ref Id для обзора схемы. Итак, в принципе, у вас есть три схемы: 1. Блог 2. Пользователь 3. Обзор

И вы должны запросить в блоге, кому принадлежит этот блог и обзор пользователей. Таким образом, вы можете запросить свой результат как:

BlogModel
  .find({})
  .populate({
    path : 'userId',
    populate : {
      path : 'reviewId'
    }
  })
  .exec(function (err, res) {

  })

Ответ 3

Наведение на несколько уровней

Скажите, что у вас есть пользовательская схема, которая отслеживает друзей пользователя.

var userSchema = new Schema({
  name: String,
  friends: [{ type: ObjectId, ref: 'User' }]
});

Populate позволяет вам получить список друзей пользователя, но что, если вы также хотели пользователей друзей друзей? Укажите параметр populate, чтобы указать mongoose заполнить массив друзей всех друзей пользователя:

User.findOne({ name: 'Val' }).populate({
    path: 'friends',
    // Get friends of friends - populate the 'friends' array for every friend
    populate: { path: 'friends' }
});

Ссылка: http://mongoosejs.com/docs/populate.html#deep-populate

Ответ 4

Возможно, слишком поздно, но я написал плагин Mongoose для выполнения глубокой популяции на любых произвольных вложенных уровнях. При регистрации этого плагина вы можете заполнять статьи категорий и учетные записи только одной строкой:

Category.deepPopulate(categories, 'articles.account', cb)

Вы также можете указать параметры заполнения для управления такими вещами, как limit, select... для каждого заполненного пути. Ознакомьтесь с документацией плагина для получения дополнительной информации.

Ответ 5

Самый простой способ выполнить это в 3.6 - это использовать Model.populate.

User.findById(user.id).select('-salt -hashedPassword').populate('favorites.things').exec(function(err, user){
    if ( err ) return res.json(400, err);

    Thing.populate(user.favorites.things, {
        path: 'creator'
        , select: '-salt -hashedPassword'
    }, function(err, things){
        if ( err ) return res.json(400, err);

        user.favorites.things = things;

        res.send(user.favorites);
    });
});

Ответ 6

Извините, что разорвал ваш пузырь, но там нет прямого поддерживаемого решения. Что касается Github issue # 601, он выглядит мрачным. Согласно примечаниям 3.6, похоже, что разработчики признали, что проблема удовлетворена ручным рекурсивным/глубоким населением.

Итак, из примечаний к выпуску рекомендуемый метод заключается в том, чтобы вложенные вызовы в обратном вызове, так что в вашей функции exec() используйте categories.populate для дальнейшего заполнения перед отправкой ответа.

Ответ 7

globals.models.Category.find()
  .where('issue', req.params.id)
  .sort('order')
  .populate('articles')
  .exec(function(err, categories) {

    globals.models.Account.populate(categories, 'articles.account', function(err, deepResults){

      // deepResult is populated with all three relations
      console.log(deepResults[0].articles[0].account);

    });
});

Следующий пример вдохновлен вопросом, заданным @codephobia, и заполняет два уровня многих отношений. Сначала выберите a user, заполните его массив связанных order и включите каждый orderDetail.

user.model.findOne()
  .where('email', '***@****.com')
  .populate('orders')
  .exec(function(err, user) {

    orderDetail.model.populate(user, 'orders.orderDetails', function(err, results){

      // results -> user.orders[].orderDetails[] 
    });
});

Это отлично работает в 3.8.8, но должно работать в 3.6.x.

Ответ 8

Эта концепция глубокого населения. Здесь Календарь, Подписка, Пользователь, Квартира являются моделями мангуста ODM на разных уровнях.

Calendar.find({}).populate({
      path: 'subscription_id',model: 'Subscription',
         populate: {path: 'user_id',model: 'User',
           populate: {path: 'apartment_id',model: 'Apartment',
              populate: {path: 'caterer_nonveg_id',
                          model: 'Caterer'}}}}).exec(function(err,data){ 
                          if(!err){
                             console.log('data all',data)
                           }
                           else{
                             console.log('err err err',err)
                            }
                   });