mongodb - many - multiple populate mongoose
Mangosta: poblaciĆ³n profunda(poblar un campo poblado) (7)
En primer lugar, actualice la mangosta 3 a 4 y luego use la forma más sencilla para la población profunda en mangosta, tal como se muestra a continuación:
Supongamos que tiene el esquema de Blog que tiene ID de usuario como ID de referencia y luego en Usuario tiene alguna revisión como ID de referencia para revisión de esquema. Entonces, básicamente, tienes tres esquemas: 1. Blog 2. Usuario 3. Revisión
Y, debe consultar desde el blog, qué usuario posee este blog y la opinión del usuario. Para que pueda consultar su resultado como:
<BlogModel>.find({}).populate({path : ''userId'', populate : {path : ''reviewId''}}).exec(function (err, res) {
})
Tengo el modelo de Category
:
Category:
...
articles: [{type:ObjectId, ref:''Article''}]
El modelo de artículo contiene ref. Account model
.
Article:
...
account: {type:ObjectId, ref:''Account''}
Entonces, con el modelo de categoría de articles
poblados, será:
{ //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'' }
La pregunta es: ¿cómo llenar el subcampo (cuenta) de un campo poblado ([artículos])? Así es como lo hago ahora:
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
Sé que fue discutido aquí: Mangosta: poblar un campo poblado pero no se encontró una solución real
La forma más sencilla de lograr esto en 3.6 es utilizar 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);
});
});
Lamento estallar tu burbuja, pero no hay una solución directamente compatible con esto. En cuanto al número 601 de Github , parece sombrío. De acuerdo con las notas de la versión 3.6 , parece que los desarrolladores reconocieron que el problema es feliz con la población manual recursiva / profunda.
Por lo tanto, a partir de las notas de la versión, el método recomendado es anidar las llamadas pobladas en la devolución de llamada, por lo que en su función exec()
, use categories.populate
para completar más antes de enviar una respuesta.
Mongoose tiene ahora un nuevo método Model.populate
para asociaciones profundas:
https://github.com/LearnBoost/mongoose/issues/1377#issuecomment-15911192
Poblando a través de múltiples niveles
Supongamos que tiene un esquema de usuario que realiza un seguimiento de los amigos del usuario.
var userSchema = new Schema({
name: String,
friends: [{ type: ObjectId, ref: ''User'' }]
});
Populate te permite obtener una lista de los amigos de un usuario, pero ¿y si también quisieras los amigos de un amigo? Especifique la opción populate para indicar a mongoose que complete el conjunto de amigos de todos los amigos del usuario:
User.findOne({ name: ''Val'' }).populate({
path: ''friends'',
// Get friends of friends - populate the ''friends'' array for every friend
populate: { path: ''friends'' }
});
Referencia: http://mongoosejs.com/docs/populate.html#deep-populate
Puede ser un poco tarde, pero escribí un plugin Mongoose para realizar una población profunda en cualquier nivel anidado arbitrario. Con este complemento registrado, puede completar los artículos y las cuentas de la categoría con solo una línea:
Category.deepPopulate(categories, ''articles.account'', cb)
También puede especificar opciones de relleno para controlar cosas como limit
, select
... para cada ruta poblada. Consulte la documentación del complemento para obtener más información.
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);
});
});
El siguiente ejemplo está inspirado en la pregunta formulada @codephobia y llena dos niveles de muchas relaciones. Primero busque un user
, orderDetail
su matriz de order
relacionadas e incluya cada 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[]
});
});
Esto funciona bien en 3.8.8
pero debería funcionar en 3.6.x