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

Заполнение вложенного массива в мангусте

Как я могу заполнить "компоненты" в документе примера:

  {
    "__v": 1,
    "_id": "5252875356f64d6d28000001",
    "pages": [
      {
        "__v": 1,
        "_id": "5252875a56f64d6d28000002",
        "page": {
          "components": [
            "525287a01877a68528000001"
          ]
        }
      }
    ],
    "author": "Book Author",
    "title": "Book Title"
  }

Это мой JS, где я получаю документ Mongoose:

  Project.findById(id).populate('pages').exec(function(err, project) {
    res.json(project);
  });
4b9b3361

Ответ 1

Mongoose 4.5 поддерживает этот

Project.find(query)
  .populate({ 
     path: 'pages',
     populate: {
       path: 'components',
       model: 'Component'
     } 
  })
  .exec(function(err, docs) {});

Ответ 2

Это работает для меня:

 Project.find(query)
  .lean()
  .populate({ path: 'pages' })
  .exec(function(err, docs) {

    var options = {
      path: 'pages.components',
      model: 'Component'
    };

    if (err) return res.json(500);
    Project.populate(docs, options, function (err, projects) {
      res.json(projects);
    });
  });

Документация: Model.populate

Ответ 3

Как уже отмечалось, Mongoose 4 поддерживает это. Очень важно отметить, что вы можете проходить глубже, чем один уровень, если это необходимо, хотя это не указано в документации:

Project.findOne({name: req.query.name})
    .populate({
        path: 'threads',
        populate: {
            path: 'messages', 
            model: 'Message',
            populate: {
                path: 'user',
                model: 'User'
            }
        }
    })

Ответ 4

Вы можете заполнить несколько вложенных документов, как это.

   Project.find(query)
    .populate({ 
      path: 'pages',
      populate: [{
       path: 'components',
       model: 'Component'
      },{
        path: 'AnotherRef',
        model: 'AnotherRef',
        select: 'firstname lastname'
      }] 
   })
   .exec(function(err, docs) {});

Ответ 5

Я нашел, что это очень полезно, создавая feathersjs до hook, чтобы заполнить соотношение 2 ref level deep. Модели мангуста просто имеют

tables = new Schema({
  ..
  tableTypesB: { type: Schema.Types.ObjectId, ref: 'tableTypesB' },
  ..
}
tableTypesB = new Schema({
  ..
  tableType: { type: Schema.Types.ObjectId, ref: 'tableTypes' },
  ..
}

то в feathersjs перед hook:

module.exports = function(options = {}) {
  return function populateTables(hook) {
    hook.params.query.$populate = {
      path: 'tableTypesB',
      populate: { path: 'tableType' }
    }

    return Promise.resolve(hook)
  }
}

Так просто по сравнению с некоторыми другими методами, которые я пытался достичь.

Ответ 6

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

Project.aggregate([
  { "$match": { "_id": mongoose.Types.ObjectId(id) } },
  { "$lookup": {
    "from": Pages.collection.name,
    "let": { "pages": "$pages" },
    "pipeline": [
      { "$match": { "$expr": { "$in": [ "$_id", "$$pages" ] } } },
      { "$lookup": {
        "from": Component.collection.name,
        "let": { "components": "$components" },
        "pipeline": [
          { "$match": { "$expr": { "$in": [ "$_id", "$$components" ] } } },
        ],
        "as": "components"
      }},
    ],
    "as": "pages"
  }}
])

Ответ 7

Я нашел этот вопрос в другом вопросе, который был специфичен для KeystoneJS, но был помечен как дубликат. Если кто-то здесь может искать ответ Keystone, я так и сделал свой глубокий запрос в Keystone.

Mongoose двухуровневая популяция с использованием KeystoneJs [дубликаты]

exports.getStoreWithId = function (req, res) {
    Store.model
        .find()
        .populate({
            path: 'productTags productCategories',
            populate: {
                path: 'tags',
            },
        })
        .where('updateId', req.params.id)
        .exec(function (err, item) {
            if (err) return res.apiError('database error', err);
            // possibly more than one
            res.apiResponse({
                store: item,
            });
        });
};

Ответ 8

Удалить ссылку документа

if (err) {
    return res.json(500);
}
Project.populate(docs, options, function (err, projects) {
    res.json(projects);
});

Это сработало для меня.

if (err) {
    return res.json(500);
}
Project.populate(options, function (err, projects) {
    res.json(projects);
});