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

Mongoose: заполнение населенного поля

Я использую MongoDB в качестве хранителя журнала для своего приложения, чтобы затем синхронизировать мобильные клиенты. У меня эти модели установлены в NodeJS:

var UserArticle = new Schema({
    date: { type: Number, default: Math.round((new Date()).getTime() / 1000) }, //Timestamp!
    user: [{type: Schema.ObjectId, ref: "User"}],
    article: [{type: Schema.ObjectId, ref: "Article"}],
    place: Number,    
    read: Number,     
    starred: Number,   
    source: String
});
mongoose.model("UserArticle",UserArticle);

var Log = new Schema({
    user: [{type: Schema.ObjectId, ref: "User"}],
    action: Number, // O => Insert, 1 => Update, 2 => Delete
    uarticle: [{type: Schema.ObjectId, ref: "UserArticle"}],
    timestamp: { type: Number, default: Math.round((new Date()).getTime() / 1000) }
});
mongoose.model("Log",Log);

Когда я хочу извлечь журнал, я использую следующий код:


var log = mongoose.model('Log');
log
.where("user", req.session.user)
.desc("timestamp")
.populate("uarticle")
.populate("uarticle.article")
.run(function (err, articles) {
if (err) {
    console.log(err);
        res.send(500);
    return;
}
res.json(articles);

Как вы можете видеть, я хочу, чтобы mongoose заполнил поле "uarticle" из коллекции журнала, а затем я хочу заполнить поле "статья" в пользовательской статье ( "uarticle" ).

Но, используя этот код, Mongoose только заполняет "uarticle" , используя модель UserArticle, но не поле статьи внутри uarticle.

Можно ли выполнить его с помощью Mongoose и populate() или я должен сделать что-то еще?

Спасибо,

4b9b3361

Ответ 1

Из того, что я проверил в документации и из того, что я слышу от вас, этого не может быть достигнуто, но вы можете сами заполнить документы "uarticle.article" в функции обратного вызова.

Однако я хочу отметить еще один аспект, который я считаю более важным. У вас есть документы в коллекции. В какой справочной коллекции B, а в сборниках B есть другая ссылка на документы в коллекции C.

Вы либо делаете это неправильно (я имею в виду структуру базы данных), либо вы должны использовать реляционную базу данных, такую ​​как MySQL здесь. Власть MongoDB полагается на то, что вы можете вставлять больше информации в документы, тем самым делая меньше запросов (имея свои данные в одной коллекции). Хотя ссылка на что-то в порядке, наличие ссылки, а затем другая ссылка не похоже на то, что вы используете все преимущества MongoDB здесь.

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

Ответ 2

Для этого вы можете использовать плагин mongoose-deep-populate. Использование:

User.find({}, function (err, users) {
   User.deepPopulate(users, 'uarticle.article', function (err, users) {
      // now each user document includes uarticle and each uarticle includes article
   })
})

Отказ от ответственности: я являюсь автором плагина.

Ответ 3

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

    applicantListToExport: function (query, callback) {
      this
       .find(query).select({'advtId': 0})
       .populate({
          path: 'influId',
          model: 'influencer',
          select: { '_id': 1,'user':1},
          populate: {
            path: 'userid',
            model: 'User'
          }
       })
     .populate('campaignId',{'campaignTitle':1})
     .exec(callback);
    }

Ответ 4

как насчет чего-то типа:

populate_deep = function(type, instance, complete, seen)
{
  if (!seen)
    seen = {};
  if (seen[instance._id])
  {
    complete();
    return;
  }
  seen[instance._id] = true;
  // use meta util to get all "references" from the schema
  var refs = meta.get_references(meta.schema(type));
  if (!refs)
  {
    complete();
    return;
  }
  var opts = [];
  for (var i=0; i<refs.length; i++)
    opts.push({path: refs[i].name, model: refs[i].ref});
  mongoose.model(type).populate(instance, opts, function(err,o){
    utils.forEach(refs, function (ref, next) {
      if (ref.is_array)
        utils.forEach(o[ref.name], function (v, lnext) {
          populate_deep(ref.ref_type, v, lnext, seen);
        }, next);
      else
        populate_deep(ref.ref_type, o[ref.name], next, seen);
    }, complete);
  });
}

meta utils грубо... хочу src?