मैं Mongoose में किसी दस्तावेज़ को कैसे अपडेट / अपग्रेड करूं?


367

शायद यह समय है, शायद यह मुझे विरल प्रलेखन में डूब रहा है और मानसून में अद्यतन करने की अवधारणा के आसपास मेरे सिर को लपेटने में सक्षम नहीं है :)

यहाँ सौदा है:

मेरे पास एक संपर्क स्कीमा और मॉडल (छोटा गुण है):

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var mongooseTypes = require("mongoose-types"),
    useTimestamps = mongooseTypes.useTimestamps;


var ContactSchema = new Schema({
    phone: {
        type: String,
        index: {
            unique: true,
            dropDups: true
        }
    },
    status: {
        type: String,
        lowercase: true,
        trim: true,
        default: 'on'
    }
});
ContactSchema.plugin(useTimestamps);
var Contact = mongoose.model('Contact', ContactSchema);

मुझे क्लाइंट से एक अनुरोध प्राप्त होता है, जिसमें मुझे उन फ़ील्ड्स की आवश्यकता होती है जो मेरे मॉडल का उपयोग करते हैं और इसके अनुसार:

mongoose.connect(connectionString);
var contact = new Contact({
    phone: request.phone,
    status: request.status
});

और अब हम समस्या तक पहुँचते हैं:

  1. अगर मैं कॉल करता contact.save(function(err){...})हूं तो मुझे एक त्रुटि मिलेगी यदि उसी फोन नंबर के साथ संपर्क पहले से मौजूद है (जैसा कि अपेक्षित है - अद्वितीय)
  2. मैं update()संपर्क पर कॉल नहीं कर सकता , क्योंकि यह विधि किसी दस्तावेज़ पर मौजूद नहीं है
  3. यदि मैं मॉडल पर अपडेट को कॉल करता हूं:
    Contact.update({phone:request.phone}, contact, {upsert: true}, function(err{...})
    मैं कुछ प्रकार के अनंत लूप में आता हूं, क्योंकि Mongoose अपडेट कार्यान्वयन स्पष्ट रूप से दूसरे पैरामीटर के रूप में ऑब्जेक्ट नहीं चाहता है।
  4. यदि मैं ऐसा ही करता हूं, लेकिन दूसरे पैरामीटर में मैं अनुरोध गुण के एक सहयोगी सरणी को पास {status: request.status, phone: request.phone ...}करता हूं - यह काम करता है - लेकिन फिर मेरे पास विशिष्ट संपर्क का कोई संदर्भ नहीं है createdAtऔर इसके और updatedAtगुणों का पता नहीं लगा सकता है ।

तो नीचे की रेखा, आखिरकार मैंने कोशिश की: एक दस्तावेज दिया contact, मैं इसे कैसे अपडेट करूं अगर यह मौजूद है, या इसे जोड़ नहीं तो क्या होगा?

आपके समय के लिए धन्यवाद।


क्या में hooking के बारे में preके लिए save?
शामून

जवाबों:


427

Mongoose अब findOneAndUpdate (MongoDB findAndModify को कॉल करता है ) के साथ मूल रूप से इसका समर्थन करता है ।

यदि यह मौजूद नहीं है, तो upser = true विकल्प ऑब्जेक्ट बनाता है। झूठे के लिए चूक

var query = {'username': req.user.username};
req.newData.username = req.user.username;

MyModel.findOneAndUpdate(query, req.newData, {upsert: true}, function(err, doc) {
    if (err) return res.send(500, {error: err});
    return res.send('Succesfully saved.');
});

पुराने संस्करणों में Mongoose इस पद्धति से इन हुकों का समर्थन नहीं करता है:

  • चूक
  • setters
  • प्रमाणकों
  • मध्यस्थ

17
यह अप टू डेट उत्तर होना चाहिए। अधिकांश अन्य दो कॉल का उपयोग करते हैं या (मेरा मानना ​​है) देशी मोंगोडब ड्राइवर पर वापस आते हैं।
हूगी

10
findOneAndUpdate के साथ समस्या यह है कि प्री-सेव को निष्पादित नहीं किया जाएगा।
a77icu5

2
Mongoose या MongoDB में एक बग की तरह लगता है?
पास्कलियस

8
डॉक्स से: "... findAndModify हेल्पर्स का उपयोग करते समय, निम्नलिखित लागू नहीं होते हैं: चूक,
बसने वाले

2
@ जैमीहुटर यह डिफ़ॉल्ट रूप से सेट नहीं है, यह एक कस्टम संपत्ति है
पास्कलियस

194

मैं बस एक ही समस्या को हल करने की कोशिश कर रहा एक ठोस 3 घंटे जला दिया। विशेष रूप से, मैं पूरे दस्तावेज़ को "बदलना" चाहता था यदि यह मौजूद है, या अन्यथा इसे डालें। यहाँ समाधान है:

var contact = new Contact({
  phone: request.phone,
  status: request.status
});

// Convert the Model instance to a simple object using Model's 'toObject' function
// to prevent weirdness like infinite looping...
var upsertData = contact.toObject();

// Delete the _id property, otherwise Mongo will return a "Mod on _id not allowed" error
delete upsertData._id;

// Do the upsert, which works like this: If no Contact document exists with 
// _id = contact.id, then create a new doc using upsertData.
// Otherwise, update the existing doc with upsertData
Contact.update({_id: contact.id}, upsertData, {upsert: true}, function(err{...});

मैंने Mongoose प्रोजेक्ट पेज पर एक मुद्दा बनाया था जिसमें अनुरोध किया गया था कि इस बारे में जानकारी डॉक्स में जोड़ी जाए।


1
फ़िलहाल प्रलेखन खराब लग रहा है। एपीआई डॉक्स में कुछ है (पृष्ठ पर "अपडेट" के लिए खोजें) इस तरह दिखता है: MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);औरMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, fn);
17

मामले के लिए दस्तावेज़ नहीं मिला है, जो _id का उपयोग किया जाता है? Mongoose इसे उत्पन्न करता है या वह जो खिलाफ था?
हैदर

91

तुम साथ थे

Contact.update({phone:request.phone}, contact, {upsert: true}, function(err){...})

लेकिन आपका दूसरा पैरामीटर उदाहरण के लिए संशोधन ऑपरेटर के साथ एक वस्तु होना चाहिए

Contact.update({phone:request.phone}, {$set: { phone: request.phone }}, {upsert: true}, function(err){...})

15
मुझे नहीं लगता कि आपको {$set: ... }यहां इसके स्वचालित रूप के रूप में मेरे पढ़ने की आवश्यकता है
CpILL

5
हाँ, मोंगोज़ कहते हैं कि यह सब कुछ $ सेट में बदल जाता है
अनुदान

1
यह लिखते समय यह मान्य था, मैं अब MongoDB का उपयोग नहीं करता हूं इसलिए मैं हाल के महीनों में बदलावों के लिए बात नहीं कर सकता: D
chrixian

5
यदि आप समय-समय पर देशी ड्राइवर का उपयोग करने जा रहे हैं, तो $ सेट का उपयोग न करना एक बुरी आदत हो सकती है।
21-30 में UpTheCreek

आप एक डालने के मामले में केवल कुछ फ़ील्ड सेट करने के लिए $ $ और $ setOnInsert का उपयोग कर सकते हैं
जस्टिन

73

खैर, मैंने लंबे समय तक इंतजार किया और कोई जवाब नहीं दिया। अंत में पूरा अपडेट / अपर्चर अप्रोच दिया और साथ गया:

ContactSchema.findOne({phone: request.phone}, function(err, contact) {
    if(!err) {
        if(!contact) {
            contact = new ContactSchema();
            contact.phone = request.phone;
        }
        contact.status = request.status;
        contact.save(function(err) {
            if(!err) {
                console.log("contact " + contact.phone + " created at " + contact.createdAt + " updated at " + contact.updatedAt);
            }
            else {
                console.log("Error: could not save contact " + contact.phone);
            }
        });
    }
});

क्या यह काम करता है? हां। क्या मैं इससे खुश हूं? शायद ऩही। एक के बजाय 2 DB कॉल।
उम्मीद है कि भावी मानगो कार्यान्वयन एक Model.upsertसमारोह के साथ होगा ।


2
यह उदाहरण एक डॉक्यूमेंट फॉर्म में मल्टी और अपर्चर विकल्पों को निर्दिष्ट करने के लिए MongoDB 2.2 में जोड़े गए इंटरफ़ेस का उपयोग करता है। .. शामिल हैं :: /includes/fact-upsert-multi-options.rst प्रलेखन यह कह रहा है, यहाँ से जाने के लिए पता नहीं है।
डोनाल्ड डेरेक

1
हालांकि यह काम करना चाहिए, अब आप 2 ऑपरेशन (खोज, अद्यतन) चला रहे हैं, जब केवल 1 (मुखर) की आवश्यकता है। @chrixian ऐसा करने का सही तरीका दिखाता है।
सम्मानTheCode

12
यह ध्यान देने योग्य है कि यह एकमात्र उत्तर है जो मोंगोज़ के वैध को किक करने की अनुमति देता है। डॉक्स के अनुसार , यदि आप अपडेट कहते हैं तो सत्यापन नहीं होता है।
टॉम स्पेन्सर

@fiznool ऐसा लगता है कि आप runValidators: trueकिसी अपडेट के दौरान मैन्युअल रूप से विकल्प में पास हो सकते हैं : अपडेट डॉक्स (हालांकि, अपडेट वैलिडेटर केवल $setऔर $unsetसंचालन पर चलते हैं )
डैनी

यदि आपको .upsert()सभी मॉडलों पर उपलब्ध होने की आवश्यकता है, तो इस आधार पर मेरा उत्तर देखें । stackoverflow.com/a/50208331/1586406
स्पोंडोब

24

बहुत सुंदर समाधान आप वादे की श्रृंखला का उपयोग करके प्राप्त कर सकते हैं:

app.put('url', (req, res) => {

    const modelId = req.body.model_id;
    const newName = req.body.name;

    MyModel.findById(modelId).then((model) => {
        return Object.assign(model, {name: newName});
    }).then((model) => {
        return model.save();
    }).then((updatedModel) => {
        res.json({
            msg: 'model updated',
            updatedModel
        });
    }).catch((err) => {
        res.send(err);
    });
});

इसे क्यों नहीं उखाड़ा गया? एक महान समाधान की तरह लगता है और बहुत ही सुंदर है
MadOgre

शानदार समाधान, वास्तव में मुझे पुनर्विचार किया कि मैं वादे कैसे करता हूं।
लक्स

4
इससे भी अधिक सुरुचिपूर्ण के पुनर्लेखन के लिए किया जाएगा (model) => { return model.save(); }के रूप में model => model.save(), और भी (err) => { res.send(err); }रूप में err => res.send(err);)
जेरेमी Thille

1
ज्यादा जानकारी कहाँ मिलेगी?
V0LT3RR4

17

मैं मानगो का अनुचर हूं। एक डॉक्टर को उखाड़ने का अधिक आधुनिक तरीका Model.updateOne()फ़ंक्शन का उपयोग करना है

await Contact.updateOne({
    phone: request.phone
}, { status: request.status }, { upsert: true });

यदि आपको उत्थान डॉक्टर की आवश्यकता है, तो आप उपयोग कर सकते हैं Model.findOneAndUpdate()

const doc = await Contact.findOneAndUpdate({
    phone: request.phone
}, { status: request.status }, { upsert: true });

मुख्य उपाय यह है कि आपको filterपैरामीटर में अद्वितीय गुणों को updateOne()या पैरामीटर में findOneAndUpdate()और अन्य गुणों को डालने की आवश्यकता है update

यहाँ Mongoose के साथ दस्तावेज़ों को बनाए रखने पर एक ट्यूटोरियल है ।


15

मैंने इस प्रश्न का उत्तर देने के लिए एक StackOverflow खाता JUST बनाया। फलविहीन रूप से इंटरवेब्स की खोज करने के बाद मैंने सिर्फ खुद कुछ लिखा। यह मैंने ऐसा किया है इसलिए इसे किसी भी मॉडल पर लागू किया जा सकता है। या तो इस फ़ंक्शन को आयात करें या इसे सीधे अपने कोड में जोड़ें जहां आप अपडेट कर रहे हैं।

function upsertObject (src, dest) {

  function recursiveFunc (src, dest) {
    _.forOwn(src, function (value, key) {
      if(_.isObject(value) && _.keys(value).length !== 0) {
        dest[key] = dest[key] || {};
        recursiveFunc(src[key], dest[key])
      } else if (_.isArray(src) && !_.isObject(src[key])) {
          dest.set(key, value);
      } else {
        dest[key] = value;
      }
    });
  }

  recursiveFunc(src, dest);

  return dest;
}

फिर एक आम दस्तावेज़ को आगे बढ़ाने के लिए,

YourModel.upsert = function (id, newData, callBack) {
  this.findById(id, function (err, oldData) {
    if(err) {
      callBack(err);
    } else {
      upsertObject(newData, oldData).save(callBack);
    }
  });
};

इस समाधान के लिए 2 DB कॉल की आवश्यकता हो सकती है, हालांकि आपको इसका लाभ मिलता है,

  • अपने मॉडल के विरुद्ध स्कीमा सत्यापन क्योंकि आप उपयोग कर रहे हैं। Save ()
  • आप अपने अपडेट कॉल में मैनुअल एन्यूमरेशन के बिना गहरी नेस्टेड ऑब्जेक्ट्स को बढ़ा सकते हैं, इसलिए यदि आपका मॉडल बदलता है तो आपको अपने कोड को अपडेट करने के लिए परेशान होने की आवश्यकता नहीं है

बस याद रखें कि गंतव्य ऑब्जेक्ट हमेशा स्रोत को ओवरराइड करेगा भले ही स्रोत का मौजूदा मूल्य हो

इसके अलावा, सरणियों के लिए, यदि मौजूदा ऑब्जेक्ट में इसे बदलने वाले की तुलना में लंबा सरणी है तो पुराने सरणी के अंत में मान बने रहेंगे। संपूर्ण सरणी को बनाए रखने का एक आसान तरीका यह है कि पुराने सरणी को सेट करने से पहले एक खाली सरणी होने के लिए सेट करें यदि आप ऐसा करना चाहते हैं।

अद्यतन - 01/16/2016 अगर मैंने आदिम मूल्यों की एक सरणी है, तो इसके लिए एक अतिरिक्त शर्त जोड़ी है, मानगो को "सेट" फ़ंक्शन का उपयोग किए बिना सरणी अपडेट होने का एहसास नहीं है।


2
केवल इसके लिए एसीसी बनाने के लिए +1: पी विश I मैं केवल .save () का उपयोग करने के लिए एक और + 1 दे सकता है, becaunse findOneAndUpate () हमें सत्यापनकर्ता और पूर्व, पोस्ट, आदि सामान का उपयोग करने में असमर्थ बनाता है। धन्यवाद, मैं इसे भी
जाँचता

क्षमा करें, लेकिन यह यहाँ काम नहीं किया :( मुझे कॉल स्टैक का आकार पार हो गया
user1576978

आप कौन से संस्करण का उपयोग कर रहे हैं? मैं 2.4.1 संस्करण का उपयोग कर रहा हूँ धन्यवाद!
हारून मस्त

इसके अलावा, आप कितनी जटिल वस्तुओं को उखाड़ रहे हैं? यदि वे बहुत बड़े हैं तो नोड प्रक्रिया ऑब्जेक्ट्स को मर्ज करने के लिए आवश्यक पुनरावर्ती कॉल की संख्या को संभालने में सक्षम नहीं हो सकती है।
आरोन मस्त

मैंने इसका उपयोग किया, लेकिन if(_.isObject(value) && _.keys(value).length !== 0) {स्टैक ओवरफ्लो को रोकने के लिए गार्ड की स्थिति में जोड़ना पड़ा । लॉडश 4+ यहाँ गैर keysकॉल वैल्यू को ऑब्जेक्ट्स में बदलना प्रतीत होता है इसलिए रिकर्सिव गार्ड हमेशा सही था। शायद वहाँ एक बेहतर तरीका है, लेकिन इसके लगभग मेरे लिए अब काम कर रहा है ...
रिचर्ड जी

12

मुझे एक संग्रह में एक दस्तावेज़ को अद्यतन / अद्यतित करने की आवश्यकता थी, जो मैंने किया वह इस तरह से एक नया ऑब्जेक्ट शाब्दिक बनाना था:

notificationObject = {
    user_id: user.user_id,
    feed: {
        feed_id: feed.feed_id,
        channel_id: feed.channel_id,
        feed_title: ''
    }
};

डेटा से बना है जो मुझे अपने डेटाबेस में कहीं और से मिलता है और फिर मॉडल पर अपडेट कॉल करता है

Notification.update(notificationObject, notificationObject, {upsert: true}, function(err, num, n){
    if(err){
        throw err;
    }
    console.log(num, n);
});

यह वह ouput है जो मुझे पहली बार स्क्रिप्ट चलाने के बाद मिला है:

1 { updatedExisting: false,
    upserted: 5289267a861b659b6a00c638,
    n: 1,
    connectionId: 11,
    err: null,
    ok: 1 }

और यह आउटपुट है जब मैं दूसरी बार स्क्रिप्ट चलाता हूं:

1 { updatedExisting: true, n: 1, connectionId: 18, err: null, ok: 1 }

मैं 3.6.16 संस्करण का उपयोग कर रहा हूँ


10
app.put('url', function(req, res) {

        // use our bear model to find the bear we want
        Bear.findById(req.params.bear_id, function(err, bear) {

            if (err)
                res.send(err);

            bear.name = req.body.name;  // update the bears info

            // save the bear
            bear.save(function(err) {
                if (err)
                    res.send(err);

                res.json({ message: 'Bear updated!' });
            });

        });
    });

यहां मानगो में अपडेट पद्धति को हल करने के लिए एक बेहतर तरीका है, आप अधिक जानकारी के लिए स्कॉच.आईओ की जांच कर सकते हैं । यह निश्चित रूप से मेरे लिए काम किया !!!


5
यह सोचने की गलती है कि यह MongoDB के अपडेट के समान है। यह परमाणु नहीं है।
वैलेंटाइन वेस्लेन्क

1
मैं @ValentinWaeselynck उत्तर का बैकअप लेना चाहता हूं। स्कॉच का कोड साफ है - लेकिन आप एक दस्तावेज़ ला रहे हैं और फिर अपडेट कर रहे हैं। उस प्रक्रिया के बीच में दस्तावेज़ को बदला जा सकता था।
निक पिनेडा

8

एक बग 2.6 में पेश किया गया है, और 2.7 को भी प्रभावित करता है

ऊपरवाला 2.4 पर सही तरीके से काम करता था

https://groups.google.com/forum/# .topic / mongodb- user / UcKvx4p4hnY https://jira.mongodb.org/browse/SERVER-13843

जरा गौर करें, इसमें कुछ महत्वपूर्ण जानकारी शामिल है

अपडेट:

इसका मतलब यह नहीं है कि ऊपर काम नहीं करता है। यहाँ इसका उपयोग करने का एक अच्छा उदाहरण दिया गया है:

User.findByIdAndUpdate(userId, {online: true, $setOnInsert: {username: username, friends: []}}, {upsert: true})
    .populate('friends')
    .exec(function (err, user) {
        if (err) throw err;
        console.log(user);

        // Emit load event

        socket.emit('load', user);
    });

7

आप बस इसके साथ रिकॉर्ड को अपडेट कर सकते हैं और प्रतिक्रिया में अद्यतन डेटा प्राप्त कर सकते हैं

router.patch('/:id', (req, res, next) => {
    const id = req.params.id;
    Product.findByIdAndUpdate(id, req.body, {
            new: true
        },
        function(err, model) {
            if (!err) {
                res.status(201).json({
                    data: model
                });
            } else {
                res.status(500).json({
                    message: "not found any relative data"
                })
            }
        });
});

5

यह मेरे लिए काम किया।

app.put('/student/:id', (req, res) => {
    Student.findByIdAndUpdate(req.params.id, req.body, (err, user) => {
        if (err) {
            return res
                .status(500)
                .send({error: "unsuccessful"})
        };
        res.send({success: "success"});
    });

});


धन्यवाद। यह वही था जो अंत में मेरे लिए काम करता था!
लुइस फित्रो

4

मिडलवेयर और वैलिडेटर्स को कॉल करते समय बनाने / अपडेट करने का सबसे सरल तरीका यहां दिया गया है।

Contact.findOne({ phone: request.phone }, (err, doc) => {
    const contact = (doc) ? doc.set(request) : new Contact(request);

    contact.save((saveErr, savedContact) => {
        if (saveErr) throw saveErr;
        console.log(savedContact);
    });
})

3

यहां पहुंचने वाले किसी भी व्यक्ति के लिए अभी भी हुक समर्थन के साथ "उत्थान" के लिए एक अच्छा समाधान की तलाश है, यह वही है जो मैंने परीक्षण किया है और काम कर रहा है। इसके लिए अभी भी 2 DB कॉल की आवश्यकता होती है, लेकिन एक कॉल में मैंने जितनी भी कोशिश की है, उससे कहीं अधिक स्थिर है।

// Create or update a Person by unique email.
// @param person - a new or existing Person
function savePerson(person, done) {
  var fieldsToUpdate = ['name', 'phone', 'address'];

  Person.findOne({
    email: person.email
  }, function(err, toUpdate) {
    if (err) {
      done(err);
    }

    if (toUpdate) {
      // Mongoose object have extra properties, we can either omit those props
      // or specify which ones we want to update.  I chose to update the ones I know exist
      // to avoid breaking things if Mongoose objects change in the future.
      _.merge(toUpdate, _.pick(person, fieldsToUpdate));
    } else {      
      toUpdate = person;
    }

    toUpdate.save(function(err, updated, numberAffected) {
      if (err) {
        done(err);
      }

      done(null, updated, numberAffected);
    });
  });
}

3

यदि जनरेटर उपलब्ध हैं तो यह और भी आसान हो जाता है:

var query = {'username':this.req.user.username};
this.req.newData.username = this.req.user.username;
this.body = yield MyModel.findOneAndUpdate(query, this.req.newData).exec();

3

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

router.post('/user/createOrUpdate', function(req,res){
    var request_data = req.body;
    var userModel = new User(request_data);
    var upsertData = userModel.toObject();
    delete upsertData._id;

    var currentUserId;
    if (request_data._id || request_data._id !== '') {
        currentUserId = new mongoose.mongo.ObjectId(request_data._id);
    } else {
        currentUserId = new mongoose.mongo.ObjectId();
    }

    User.update({_id: currentUserId}, upsertData, {upsert: true},
        function (err) {
            if (err) throw err;
        }
    );
    res.redirect('/home');

});

2
//Here is my code to it... work like ninj

router.param('contractor', function(req, res, next, id) {
  var query = Contractors.findById(id);

  query.exec(function (err, contractor){
    if (err) { return next(err); }
    if (!contractor) { return next(new Error("can't find contractor")); }

    req.contractor = contractor;
    return next();
  });
});

router.get('/contractors/:contractor/save', function(req, res, next) {

    contractor = req.contractor ;
    contractor.update({'_id':contractor._id},{upsert: true},function(err,contractor){
       if(err){ 
            res.json(err);
            return next(); 
            }
    return res.json(contractor); 
  });
});


--

2
User.findByIdAndUpdate(req.param('userId'), req.body, (err, user) => {
    if(err) return res.json(err);

    res.json({ success: true });
});

हालांकि यह कोड स्निपेट समस्या को हल कर सकता है, यह इस बात की व्याख्या नहीं करता है कि यह प्रश्न का उत्तर क्यों या कैसे देता है। कृपया अपने कोड के लिए एक स्पष्टीकरण शामिल करें , क्योंकि यह वास्तव में आपके पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और उन लोगों को आपके कोड सुझाव के कारणों का पता नहीं चल सकता है। फ्लैगर्स / समीक्षक: कोड-ओनली उत्तरों जैसे कि यह एक, डाउनवोट, डिलीट न करें!
पैट्रिक

2

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

plugins.js

export default (schema, options) => {
  schema.statics.upsert = async function(query, data) {
    let record = await this.findOne(query)
    if (!record) {
      record = new this(data)
    } else {
      Object.keys(data).forEach(k => {
        record[k] = data[k]
      })
    }
    return await record.save()
  }
}

db.js

import mongoose from 'mongoose'

import Plugins from './plugins'

mongoose.connect({ ... })
mongoose.plugin(Plugins)

export default mongoose

फिर आप जब चाहें User.upsert({ _id: 1 }, { foo: 'bar' })या जैसा YouModel.upsert({ bar: 'foo' }, { value: 1 })चाहें , कुछ कर सकते हैं।


2

मैं थोड़ी देर बाद इस मुद्दे पर वापस आया, और हारून मस्त के जवाब के आधार पर एक प्लगइन प्रकाशित करने का फैसला किया।

https://www.npmjs.com/package/mongoose-recursive-upsert

इसे एक मोंगोजोस प्लगइन के रूप में उपयोग करें। यह एक स्थैतिक विधि सेट करता है जो पास की गई वस्तु को पुन: विलय करेगा।

Model.upsert({unique: 'value'}, updateObject});

0

यह ताबूत मेरे लिए नोड के साथ काम करता है - चाल यह है कि _id ग्राहक से भेजे और वापस आने पर उसके ऑब्जेक्ट रैपर से छीन लिया जाता है और इसलिए इसे अपडेट के लिए प्रतिस्थापित किया जाना चाहिए (जब कोई _id प्रदान नहीं किया जाता है, तो इसे सम्मिलित करने और जोड़ने के लिए वापस आ जाएगा। एक)।

app.post '/new', (req, res) ->
    # post data becomes .query
    data = req.query
    coll = db.collection 'restos'
    data._id = ObjectID(data._id) if data._id

    coll.save data, {safe:true}, (err, result) ->
        console.log("error: "+err) if err
        return res.send 500, err if err

        console.log(result)
        return res.send 200, JSON.stringify result

0

मार्टिन कुजैडविक्ज़ ने ऊपर जो पोस्ट किया था उस पर निर्माण करने के लिए। मैं मूंगोज़ का उपयोग करके अपडेट करने के लिए निम्नलिखित का उपयोग करता हूं और जसन वस्तुओं का गहरा मर्ज करता हूं। मोंगोज़ में model.save () फ़ंक्शन के साथ-साथ यह मानसून को एक पूर्ण सत्यापन भी करने की अनुमति देता है जो कि अन्य मूल्यों पर निर्भर करता है। इसके लिए गहरे पैकेज की आवश्यकता है https://www.npmjs.com/package/deepmerge । लेकिन यह बहुत हल्का वजन पैकेज है।

var merge = require('deepmerge');

app.put('url', (req, res) => {

    const modelId = req.body.model_id;

    MyModel.findById(modelId).then((model) => {
        return Object.assign(model, merge(model.toObject(), req.body));
    }).then((model) => {
        return model.save();
    }).then((updatedModel) => {
        res.json({
            msg: 'model updated',
            updatedModel
        });
    }).catch((err) => {
        res.send(err);
    });
});

1
मैं NoSQL इंजेक्शन केreq.body लिए परीक्षण करने से पहले के रूप में उपयोग करने के खिलाफ सावधान रहना होगा (देखें owasp.org/index.php/Testing_for_NoSQL_injection )।
यात्रा टेक लड़के

1
@TravelingTechGuy सावधानी के लिए धन्यवाद मैं अभी भी Node और Mongoose के लिए नया हूं। क्या वैद्यों के साथ मेरा आम मॉडल एक इंजेक्शन प्रयास को पकड़ने के लिए पर्याप्त नहीं होगा?
model.save के

-5

उपरोक्त पोस्ट पढ़ने के बाद, मैंने इस कोड का उपयोग करने का निर्णय लिया:

    itemModel.findOne({'pid':obj.pid},function(e,r){
        if(r!=null)
        {
             itemModel.update({'pid':obj.pid},obj,{upsert:true},cb);
        }
        else
        {
            var item=new itemModel(obj);
            item.save(cb);
        }
    });

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


यदि यह मानगो को दो कॉल है, तो यह वास्तव में नहीं है
ह्यूगी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.