it-swarm.com.de

Mongoose bevölkern nach dem Speichern

Ich kann das Erstellerfeld für ein neu gespeichertes Objekt nicht manuell oder automatisch ausfüllen. Die einzige Möglichkeit, die ich finden kann, besteht darin, die Objekte, die ich bereits habe, erneut abzufragen.

Dies ist das Setup:

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

Hier ziehe ich meine Haare

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

BEARBEITEN: Der neueste Mungo hat dieses Problem behoben und die Populationsfunktion hinzugefügt. Siehe die neue akzeptierte Antwort.

66
Pykler

Sie sollten in der Lage sein, die Populate-Funktion des Modells dazu zu verwenden: http://mongoosejs.com/docs/api.html#model_Model.populate Im Speicherhandler für Buch anstelle von:

book._creator = user;

sie würden etwas tun wie:

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

Wahrscheinlich zu spät eine Antwort, um Ihnen zu helfen, aber ich habe mich in letzter Zeit daran gehalten, und es könnte für andere nützlich sein.

118
user1417684

Falls noch jemand danach sucht.

Mongoose 3.6 hat eine Menge cooler Funktionen zum Auffüllen eingeführt:

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

oder:

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

mehr dazu unter: https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population

Aber auf diese Weise würden Sie immer noch den Benutzer abfragen.

Ein kleiner Trick, um dies ohne zusätzliche Anfragen zu erreichen, wäre:

book = book.toObject();
book._creator = user;
34
Eric Saboia

Um nur ein weiteres Beispiel zu erarbeiten, da es mir geholfen hat. Dies kann für diejenigen hilfreich sein, die nach dem Speichern teilweise aufgefüllte Objekte abrufen möchten. Die Methode ist auch etwas anders. Verbrachte mehr als ein oder zwei Stunden, um nach dem richtigen Weg zu suchen.

  post.save(function(err) {
    if (err) {
      return res.json(500, {
        error: 'Cannot save the post'
      });
    }
    post.populate('group', 'name').populate({
      path: 'wallUser',
      select: 'name picture'
    }, function(err, doc) {
      res.json(doc);
    });
  });
11
Pratik Bothra

Lösung, die ein Versprechen zurückgibt (keine Rückrufe):

Dokument Nr. Verwenden

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

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

Mögliche Implementierung

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

Lesen Sie mehr über die Belegschaft hier .

10
Govind Rai

Die Lösung für mich war, execPopulate zu verwenden

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

Ich dachte, ich würde noch etwas hinzufügen, um die Dinge für mich zu verdeutlichen.

Was sehr verwirrend ist, wenn Sie nicht aufpassen, ist, dass es drei sehr unterschiedliche Bestückungsmethoden gibt. Sie sind Methoden verschiedener Objekte (Modell vs. Dokument), nehmen unterschiedliche Eingaben auf und geben unterschiedliche Ergebnisse (Document vs. Promise).

Hier sind sie für diejenigen, die verwirrt sind:

Document.prototype.populate ()

Siehe vollständige Dokumente.

Dieser bearbeitet Dokumente und gibt ein Dokument zurück. Im ursprünglichen Beispiel würde es so aussehen:

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

Da es für Dokumente funktioniert und ein Dokument zurückgibt, können Sie sie wie folgt verketten:

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

Aber sei nicht dumm wie ich und versuche es:

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

Denken Sie daran: Document.prototype.populate () gibt ein Dokument zurück, dies ist also Unsinn. Wenn Sie ein Versprechen wollen, brauchen Sie ...

Document.prototype.execPopulate ()

Siehe vollständige Dokumente.

Dies funktioniert an Dokumenten, ABER es gibt ein Versprechen zurück, das in das Dokument aufgelöst wird ..__ Mit anderen Worten, Sie können es wie folgt verwenden:

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

Das ist besser. Endlich gibt es noch ...

Model.populate ()

Siehe vollständige Dokumente.

Dieses arbeitet an Modellen und liefert ein Versprechen. Es wird daher etwas anders verwendet:

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

Hoffe das hat einigen anderen Neuankömmlingen geholfen.

5
curzmg

Leider ist dies ein seit langem bestehendes Problem mit Mungo, von dem ich glaube, dass es noch nicht gelöst ist:

https://github.com/LearnBoost/mongoose/issues/570

Was Sie tun können, ist, Ihren eigenen benutzerdefinierten Getter/Setter zu schreiben (und real_customer in einer separaten Eigenschaft). Zum Beispiel:

var get_creator = function(val) {
    if (this.hasOwnProperty( "__creator" )) {
        return this.__creator;
    }
    return val;
};
var set_creator = function(val) {
    this.__creator = val;
    return val;
};
var bookSchema = new mongoose.Schema({
  _creator: {
     type: mongoose.Schema.Types.ObjectId,
     ref: 'User',
     get: get_creator,
     set: set_creator
  },
  description: String,
});

HINWEIS: Ich habe es nicht getestet und es funktioniert möglicherweise mit .populate und bei der Einstellung der reinen ID.

1
freakish

am Ende schrieb ich einige Curry-fähige Promise-Funktionen, in denen Sie Ihr Schema, die Funktionen query_adapter und data_adapter vorab deklarieren und die Zeichenfolge auffüllen. Für eine kürzere/einfachere Implementierung einfacher.

Es ist wahrscheinlich nicht besonders effizient, aber ich fand das Ausführungsbit ziemlich elegant.

github-Datei: curry_Promises.js

declartion

const update_or_insert_Item = mDB.update_or_insert({
    schema : model.Item,
    fn_query_adapter : ({ no })=>{return { no }},
    fn_update_adapter : SQL_to_MDB.item,
    populate : "headgroup"
    // fn_err : (e)=>{return e},
    // fn_res : (o)=>{return o}
})

Ausführung

Promise.all( items.map( update_or_insert_Item ) )
.catch( console.error )
.then( console.log )
0
WouldBeNerd

Wahrscheinlich etw. mögen

Book.createAsync(bookToSave).then((savedBook) => savedBook.populateAsync("creator"));

Das wäre der schönste und am wenigsten problematische Weg, um dies zu erreichen (Verwendung von Bluebird-Versprechen).

0
kboom

Mungo 5.2.7

Das funktioniert für mich (nur sehr viel Kopfschmerzen!)

exports.create = (req, res, next) => {
  const author = req.userData;
  const postInfo = new Post({
    author,
    content: req.body.content,
    isDraft: req.body.isDraft,
    status: req.body.status,
    title: req.body.title
  });
  postInfo.populate('author', '_id email role display_name').execPopulate();
  postInfo.save()
    .then(post => {
      res.status(200).json(post);
    }).catch(error => {
      res.status(500).json(error);
    });
};
0
Whisher