2011-12-17 8 views
17

estoy usando MongoDB como encargado de registro para mi aplicación a continuación, sincronizar los clientes móviles. Tengo estos modelos establecidos en NodeJS:Mangosta: rellenar un campo rellenado

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

Cuando quiero retrive el registro utilizo el código siguientes aparatos:


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

Como se puede ver, quiero mangosta para poblar el "uarticle" campo de la colección Log y, a continuación, deseo rellenar el campo "artículo" del artículo de usuario ("uarticle").

embargo, el uso de este código, sólo se puebla Mangosta "uarticle" utilizando el Modelo de UserArticle, pero no el campo de los artículos dentro de uarticle.

¿Es posible lograrlo mediante la mangosta y poblar() o que debería hacer algo más?

Gracias,

+0

me he encontrado con el mismo problema en el que la referencia está incrustado en una matriz -> myList: [{mid: {type: Schema.ObjectId, 'ref': 'OtherModel'}, meta: [String]}]. Esto produce el siguiente error cuando intento .populate ('myList.mid') ... TypeError: no se puede llamar al método 'path' de undefined – Greg

Respuesta

16

Por lo que he comprobado en la documentación y por lo que sé de ti, esto no se puede lograr, pero se puede instalar en la "uarticle.article" documentos a sí mismo en la función de devolución de llamada.

Sin embargo, quiero señalar otro aspecto que considero más importante. Tiene documentos en la colección A que referencian la colección B, y en los documentos de la colección B tiene otra referencia a los documentos en la colección C.

Está haciendo esto mal (me refiero a la estructura de la base de datos), o debería estar usando una base de datos relacional como MySQL aquí. El poder de MongoDB se basa en el hecho de que puede incorporar más información en los documentos, por lo que tiene que realizar consultas menores (tener sus datos en una sola colección). Aunque hacer referencia a algo está bien, tener una referencia y luego otra referencia no parece que estés aprovechando al máximo MongoDB aquí.

Tal vez le gustaría compartir su situación y la estructura de base de datos para que pudiéramos ayudarle a obtener más información.

+0

La colección Logs es la única que tiene referencias raras, solo quería, porque las demás tener solo 1 referencia (para evitar repetir muchas veces los mismos datos). Creo que para evitar el uso de mucha información, no llenaré este el "libro" y el cliente hará una solicitud para obtener los detalles del artículo, solo para mantener las cosas simples y rápidas. – Francesc

+1

¿Puede dar más detalles sobre su respuesta? ¿Lo estoy leyendo bien? Debe examinarse si tiene una sola referencia. Estoy empezando en mongodb. Después de todo, muchas tablas relacionales tienen solo una clave externa. ¿Son preferibles los documentos incrustados a rellenar ref de ObjectId? – grantwparks

+0

Realmente depende de la estructura del proyecto, a veces es posible que desee duplicar los datos (inserción) para la velocidad, otras veces es probable que necesite referencia, ya que los datos se consultarán solo en ciertas condiciones. – alessioalex

0

¿qué tal algo como:

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

utilidades meta es áspera ... quiere que el src?

5

Usted puede utilizar el plugin mongoose-deep-populate para hacer esto. Uso:

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

Descargo de responsabilidad: soy el autor del complemento.

1

que enfrentan el mismo problema, pero después de horas de esfuerzos Encuentro la solution.It puede ser sin utilizar ningún plug-in externo :)

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