Вложенная эталонная популяция мангустов

У меня возникли проблемы с пониманием некоторых концепций методов mongoose populate. Сначала у меня работал встроенный подход, хотя, поскольку я опасался больших накладных расходов на данные и несинхронизированные документы, я попытался изменить парадигму на ref другие документы.

Моя схема похожа на следующую (удалены ненужные свойства):

var userSchema = mongoose.Schema({
    name: {type: String, default:''},
    favorites:{ 
        users:[{type: Schema.Types.ObjectId, ref: this}],
        places:[{type: Schema.Types.ObjectId, ref: PlaceSchema}]
    }
});

module.exports = mongoose.model('User', userSchema);

Теперь я пытаюсь получить User favorites следующим образом:

User.findOne({_id: currentUser}).exec(function(err, user){
  console.log(user);
  if (err)
    throw err;

  if(!user){
    console.log("can't find user");
  }else{ // user found
    user.populate('favorites.users');
    user.populate('favorites.places');

    // do something to the 'user.favorites' object

  }
});

Хотя это не работает должным образом, поскольку и user.favorites.users, и user.favorites.places оказываются неопределенными.

Я думал, что смогу заполнить, как указано выше, но, видимо, это не так. Из того, что я прочитал, я должен упустить что-то, указывающее (возможно) на модель refed документа? Этот поток очень нов для меня, и я немного потерян.

Могу ли я в любом случае получить массив users и places, заполнив результат моего запроса, как указано выше? Я пробовал populate в цепочке с exec, и это тоже не работает. Есть ли лучший способ достичь этого результата?

РЕДАКТИРОВАТЬ: В случае необходимости в БД документ User отображается как:

{
  "_id": "56c36b330fbc51ba19cc83ff",
  "name": "John Doe",
  "favorites": {
    "places": [],
    "users": [
      "56b9d9a45f1ada8e0c0dee27"
    ]
  }
}

РЕДАКТИРОВАТЬ: Еще пара деталей... В настоящее время я сохраняю/удаляю ссылочные ObjectIds, подобные этому (обратите внимание, что targetID - это строка):

user.favorites.users.push({ _id: mongoose.Types.ObjectId(targetID)});
user.favorites.users.pull({ _id: mongoose.Types.ObjectId(targetID)});

Кроме того, мне нужно заполнить users и places соответствующими документами также, я думаю, что это может быть неясно в моем исходном вопросе.


person Joum    schedule 16.03.2016    source источник
comment
Значение ref должно быть именем модели, на которую ссылаются, а не схемы.   -  person JohnnyHK    schedule 16.03.2016


Ответы (2)


Пытаться:

User
.findOne({_id: currentUser})
.populate('favorites.users')
.populate('favorites.places')
.exec( function (err, user) {
  // user.favorites.users
  // user.favorites.places
});
person DJeanCar    schedule 16.03.2016
comment
Возможно, я недостаточно объяснил: это сработало, но мне нужно было заполнить массивы users и places соответствующими документами. Можете ли вы указать, чего не хватает? - person Joum; 16.03.2016
comment
в основном, все, что я вижу в объекте user.favorites.users, это строки ID других пользователей... - person Joum; 16.03.2016

Что ж, я понял, что мне нужно, обратив должное внимание на документы (а также с помощью / указателями @DJeanCar (+1'd)).

С помощью документов Mongoose, касающихся заполнения на нескольких уровнях, я достиг этого решение:

User.findOne({_id: currentUser})
    .populate({path:"favorites.users", populate: "name"})
    .populate({path:"favorites.places", populate: "name"})
    .exec(function(err, user){
      if(err)
        throw err;

      if(!user){
        console.log("couldnt find source user");
      }else{
        // here, user.favorites is populated and I can do what I need with the data
      }
    });

Кроме того, из того, что я мог сказать, вы также можете передать select: "field field field" в параметрах populate(), если вам нужно отфильтровать поля документа, которые вам нужны после заполнения.

Надеюсь, это поможет кому-то с похожими проблемами!

person Joum    schedule 16.03.2016