Мангуст: заселение населенного поля - PullRequest
18 голосов
/ 17 декабря 2011

Я использую 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" из коллекции Log, а затем я хочу заполнить поле "article" в UserArticle ("uarticle").

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

Можно ли сделать это, используя Mongoose и populate (), или я должен сделать что-то еще?

Спасибо,

Ответы [ 4 ]

15 голосов
/ 17 декабря 2011

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

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

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

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

5 голосов
/ 10 декабря 2014

Вы можете использовать плагин 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
   })
})

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

2 голосов
/ 13 июня 2017

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

    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);
    }
0 голосов
/ 07 марта 2014

как насчет чего-то вроде:

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);
  });
}

мета утилиты грубые ... хочешь src?

...