119 votes

La mongole se remplit après la sauvegarde

Je ne peux pas remplir manuellement ou automatiquement le champ "créateur" d'un objet nouvellement sauvegardé... la seule solution que je trouve est de réinterroger les objets que je possède déjà, ce que je n'aimerais pas faire.

Voici l'installation :

var userSchema = new mongoose.Schema({   
  name: String,
});
var User = db.model('User', userSchema);

var bookSchema = new mongoose.Schema({
  _creator: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
  description: String,
});
var Book = db.model('Book', bookSchema);

C'est là que je m'arrache les cheveux

var user = new User();
user.save(function(err) {
    var book = new Book({
        _creator: user,
    });
    book.save(function(err){
        console.log(book._creator); // is just an object id
        book._creator = user; // still only attaches the object id due to Mongoose magic
        console.log(book._creator); // Again: is just an object id
        // I really want book._creator to be a user without having to go back to the db ... any suggestions?
    });
});

EDIT : la dernière mangouste a corrigé ce problème et ajouté la fonctionnalité de populage, voir la nouvelle réponse acceptée.

156voto

user1417684 Points 461

Vous devriez pouvoir utiliser la fonction populate du modèle pour ce faire : http://mongoosejs.com/docs/api.html#model_Model.populate Dans le gestionnaire d'enregistrement du livre, au lieu de :

book._creator = user;

vous feriez quelque chose comme :

Book.populate(book, {path:"_creator"}, function(err, book) { ... });

La réponse est probablement trop tardive pour vous aider, mais j'étais coincé sur ce point récemment, et cela pourrait être utile à d'autres.

52voto

desgnl Points 941

La solution pour moi a été d'utiliser execPopulate comme suit

const t = new MyModel(value)
return t.save().then(t => t.populate('my-path').execPopulate())

37voto

Eric Saboia Points 1

Au cas où quelqu'un serait encore à la recherche de cette information.

Mongoose 3.6 a introduit un grand nombre de fonctionnalités intéressantes pour le populage :

book.populate('_creator', function(err) {
 console.log(book._creator);
});

ou :

Book.populate(book, '_creator', function(err) {
 console.log(book._creator);
});

voir plus à : https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population

Mais de cette façon, l'utilisateur sera de nouveau interrogé.

Une petite astuce pour y arriver sans requêtes supplémentaires serait :

book = book.toObject();
book._creator = user;

29voto

Govind Rai Points 3726

La solution qui renvoie une promesse (pas de callback) :

Utiliser le document#populer

book.populate('creator').execPopulate();

// summary
doc.populate(options);               // not executed
doc.populate(options).execPopulate() // executed, returns promise

Mise en œuvre possible

var populatedDoc = doc.populate(options).execPopulate();
populatedDoc.then(doc => {
   ... 
});

Lire sur la population des documents ici .

15voto

curzmg Points 137

J'ai pensé ajouter quelque chose pour clarifier les choses pour les novices complets comme moi.

Ce qui est très déroutant si vous ne faites pas attention, c'est qu'il existe trois méthodes de remplissage très différentes. Ce sont des méthodes d'objets différents (Model vs. Document), qui prennent des entrées différentes et donnent des sorties différentes (Document vs. Promise).

Les voici pour ceux qui sont déconcertés :

Document.prototype.populate()

Voir les documents complets.

Celui-ci travaille sur des documents et renvoie un document. Dans l'exemple original, cela ressemblerait à ceci :

book.save(function(err, book) {
    book.populate('_creator', function(err, book) {
        // Do something
    })
});

Comme elle travaille sur des documents et renvoie un document, vous pouvez les enchaîner comme suit :

book.save(function(err, book) {
    book
    .populate('_creator')
    .populate('/* Some other ObjectID field */', function(err, book) {
        // Do something
    })
});

Mais ne soyez pas stupide, comme moi, et essayez de faire ça :

book.save(function(err, book) {
    book
    .populate('_creator')
    .populate('/* Some other ObjectID field */')
    .then(function(book) {
        // Do something
    })
});

Rappelez-vous : Document.prototype.populate() renvoie un document, donc c'est un non-sens. Si vous voulez une promesse, vous devez...

Document.prototype.execPopulate()

Voir les documents complets.

Celui-ci fonctionne sur les documents MAIS il renvoie une promesse qui se résout au document. En d'autres termes, vous pouvez l'utiliser comme ceci :

book.save(function(err, book) {
    book
    .populate('_creator')
    .populate('/* Some other ObjectID field */')
    .execPopulate()
    .then(function(book) {
        // Do something
    })
});

C'est mieux. Enfin, il y a...

Modèle.populate()

Voir les documents complets.

Celui-là travaille sur des modèles et renvoie une promesse. Il est donc utilisé un peu différemment :

book.save(function(err, book) {
    Book // Book not book
    .populate(book, { path: '_creator'})
    .then(function(book) {
        // Do something
    })
});

J'espère que cela a aidé d'autres nouveaux arrivants.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X