बचाने के बाद मानगो आबाद


96

मैं मैन्युअल रूप से या स्वचालित रूप से सहेजे गए ऑब्जेक्ट पर निर्माता फ़ील्ड को पॉप्युलेट नहीं कर सकता ... केवल एक ही तरीका है जो मैं पा सकता हूं उन वस्तुओं के लिए फिर से क्वेरी करना जो मेरे पास पहले से ही हैं जो मैं करने के लिए नफरत करता हूं।

यह सेटअप है:

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

यह वह जगह है जहां मैं अपने बाल खींच रहा हूं

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

संपादित करें: नवीनतम मानसून ने इस मुद्दे को निर्धारित किया और आबादी की कार्यक्षमता को जोड़ा, नए स्वीकृत उत्तर देखें।

जवाबों:


136

आपको ऐसा करने के लिए मॉडल के पॉपुलेट फ़ंक्शन का उपयोग करने में सक्षम होना चाहिए: http://mongoosejs.com/docs/api.html#model_Model.populate पुस्तक के लिए सहेजें हैंडलर में, इसके बजाय:

book._creator = user;

आप कुछ ऐसा करेंगे:

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

शायद आपकी मदद करने के लिए एक उत्तर देने में बहुत देर हो गई, लेकिन मैं हाल ही में इस पर अटक गया था, और यह दूसरों के लिए उपयोगी हो सकता है।


यह अच्छा होगा अगर यह आभासी विशेषताओं के साथ काम करे। जैसेcreator.profile
chovy

यदि उपयोगकर्ता के पास कुछ आभासी विशेषताएँ हैं तो वे शामिल नहीं हैं।
चॉबी

यह मेरे लिए काम कर रहा था, हालांकि मुझे कुछ समस्याएं थीं जब मैंने बचाने से पहले ही संदर्भ को शून्य करने की कोशिश की थी। बचाने के बाद, Book.populate को कॉल करने से पिछले संदर्भ मान के साथ फ़ील्ड को गलत तरीके से पॉप्युलेट किया गया है और मैं बाहर काम नहीं कर सकता। DB में सफलतापूर्वक अशक्त होता है।
डैनियल फ्लिपेंस

2
और यह डेटाबेस को फिर से क्वेरी नहीं करेगा ?!
नेपॉक्सएक्स

9
यह डेटाबेस को पुनः क्वेरी कर रहा है
bubakazouba

36

मामले में अभी भी किसी की तलाश है।

Mongoose 3.6 को आबाद करने के लिए बहुत सारी शानदार सुविधाएँ पेश की गई हैं:

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

या:

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

इस पर अधिक देखें: https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population

लेकिन इस तरह आप फिर भी उपयोगकर्ता के लिए क्वेरी करेंगे।

अतिरिक्त प्रश्नों के बिना इसे पूरा करने के लिए एक छोटी सी चाल होगी:

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

कर book._creator = user;के बाद save()सभी मौजूदा जवाब के बीच में ही सही जवाब है, अन्य सभी जवाब एक अतिरिक्त क्वेरी की आवश्यकता है।
Mr5o1

23

मेरे लिए समाधान का उपयोग करना था execPopulate, जैसे

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

2
बहुत बहुत धन्यवाद @ फ्रैंकोइस, आपने मेरी जान बचाई, मैं इसके लिए समाधान खोजने की कोशिश कर रहा था। FInally को वह मिल गया।
रूपेश

18

समाधान जो एक वादा लौटाता है (कोई कॉलबैक नहीं):

दस्तावेज़ का उपयोग करें # आबाद करें

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

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

संभव कार्यान्वयन

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

दस्तावेज़ आबादी के बारे में यहाँ पढ़ें ।


अच्छी चीज़। धन्यवाद
जोएल एच

11

बस विस्तृत और एक और उदाहरण देने के लिए, क्योंकि इससे मुझे मदद मिली। यह उन लोगों की मदद कर सकता है जो बचत के बाद आंशिक रूप से आबादी वाली वस्तुओं को पुनः प्राप्त करना चाहते हैं। विधि थोड़ा अलग भी है। इसे करने के सही तरीके की तलाश में एक या दो घंटे से अधिक समय बिताया।

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

9

मैंने सोचा कि मैं इसे अपने जैसे पूर्ण नॉब के लिए चीजों को स्पष्ट करने के लिए जोड़ूंगा।

यदि आप सावधान नहीं हैं तो बड़े पैमाने पर भ्रामक है कि तीन अलग-अलग आबादी वाले तरीके हैं। वे विभिन्न वस्तुओं (मॉडल बनाम दस्तावेज़) के तरीके हैं, विभिन्न इनपुट लेते हैं और विभिन्न आउटपुट (दस्तावेज़ बनाम वादा) देते हैं।

यहाँ वे उन लोगों के लिए हैं जो चकित हैं:

Document.prototype.populate ()

पूर्ण डॉक्स देखें।

यह एक दस्तावेज़ पर काम करता है और एक दस्तावेज़ लौटाता है। मूल उदाहरण में, यह इस तरह दिखेगा:

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

क्योंकि यह दस्तावेज़ों पर काम करता है और दस्तावेज़ लौटाता है, आप उन्हें एक साथ चेन कर सकते हैं:

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

लेकिन मेरी तरह मूर्ख मत बनो, और यह करने की कोशिश करो:

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

याद रखें: Document.prototype.populate () एक दस्तावेज़ लौटाता है, इसलिए यह बकवास है। यदि आप एक वादा चाहते हैं, तो आपको चाहिए ...

Document.prototype.execPopulate ()

पूर्ण डॉक्स देखें।

यह एक दस्तावेज़ पर काम करता है लेकिन यह एक वादा करता है जो दस्तावेज़ को हल करता है। दूसरे शब्दों में, आप इसे इस तरह से उपयोग कर सकते हैं:

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

वह बेहतर है। अंत में, वहाँ ...

Model.populate ()

पूर्ण डॉक्स देखें।

यह एक मॉडल पर काम करता है और एक वादा वापस करता है। इसलिए यह थोड़ा अलग तरीके से उपयोग किया जाता है:

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

आशा है कि कुछ अन्य नवागंतुकों की मदद की जाएगी।


1

Unfortunetly यह एक लंबे समय से स्थायी मुद्दा है जो मुझे लगता है कि अभी तक हल नहीं हुआ है:

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

इसके लिए आप क्या कर सकते हैं कि आप अपने लिए कस्टम गेट्टर / सेटर लिखें (और अलग संपत्ति में वास्तविक सेट करें _customer)। उदाहरण के लिए:

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

नोट: मैंने इसका परीक्षण नहीं किया और .populateशुद्ध आईडी सेट करते समय यह अजीब तरीके से काम कर सकता है ।


ऐसा लगता है कि वे इस मुद्दे को ठीक करना नहीं चाह रहे हैं।
Pykler

1
यह अंक 3.6 में तय किया गया है
mkoryak

@Pyler को वास्तव में पहले स्वीकार किए गए उत्तर को उच्चतम श्रेणी में बदलने की आवश्यकता है, क्योंकि यह उत्तर मान्य नहीं है
मैट फ्लेचर

1

Mongoose 5.2.7

यह मेरे लिए काम करता है (बस बहुत सिरदर्द!)

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

शायद sth। पसंद

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

यह काम करने के लिए सबसे अच्छा और सबसे कम समस्याग्रस्त तरीका होगा (ब्लूबर्ड वादों का उपयोग करके)।


0

कुछ करी-सक्षम वचन लिखने को समाप्त कर दिया, जहाँ आप अपने स्कीमा, query_adcape, data_adcape फ़ंक्शंस की घोषणा करते हैं और स्ट्रिंग को पहले से आबाद करते हैं। एक छोटे / सरल कार्यान्वयन के लिए आसान है।

यह शायद सुपर कुशल नहीं है, लेकिन मुझे लगा कि निष्पादन बिट काफी सुरुचिपूर्ण था।

github फ़ाइल: 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}
})

क्रियान्वयन

Promise.all( items.map( update_or_insert_Item ) )
.catch( console.error )
.then( console.log )
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.