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.
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.
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;
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);
});
});
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 .
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())
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:
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 ...
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 ...
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.
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.
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 )
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).
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);
});
};