2013-09-18 3 views
29

У меня есть Category модели:Mongoose: глубокое население (заполняется населенное поле)

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

Статья модель содержит реф к Account model.

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

Так, с населенной моделью articles Категории будет:

{ //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: Populate a populated field, но никакое реальное решение не было найдено

+0

как rroxysam сказал, '.populate ({путь:«идентификатор пользователя», заселить: {путь : 'reviewId'}}). exec (...) ' Кажется, рекурсивная логика и это имеет смысл. это работает! –

ответ

3

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

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

7

Самый простой способ сделать это в 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); 
    }); 
}); 
+0

Мне любопытно, как бы вы сделали то же самое, если user.favorites был массивом? – codephobia

+0

То же самое. Просто избавьтесь от .thing – chovy

2
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 и заполнит два уровня многих отношениях. Сначала выберите user, заполните его массив связанных order s и включите каждый 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.

17

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

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

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

+2

вы, человек. отличный плагин – r3wt

22

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

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

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

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

}) 
+0

Если бы я только прочитал ваш ответ и не потратил час моего времени на ответы выше! –

+0

Благодарим вас за отображение структуры запроса, а не только ссылку на документ. Прекрасно работает! –

12

Наполнение на нескольких уровнях

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

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

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

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

+1

Это правильное решение. Большое спасибо. – Tigin

Смежные вопросы