মঙ্গুজে আমি কীভাবে কোনও দস্তাবেজ আপডেট / উপস্থাপন করব?


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{...})
    আমি কিছু ধরণের অসীম লুপের মধ্যে চলে যাই, যেহেতু মঙ্গুজ আপডেট প্রয়োগটি স্পষ্টভাবে দ্বিতীয় প্যারামিটার হিসাবে কোনও বস্তু চায় না।
  4. যদি আমিও এটি করি তবে দ্বিতীয় প্যারামিটারে আমি অনুরোধের বৈশিষ্ট্যগুলির সাথে {status: request.status, phone: request.phone ...}কাজ করে তার একটি সহযোগী অ্যারে পাস করি - তবে তারপরে আমার নির্দিষ্ট পরিচিতির কোনও রেফারেন্স নেই createdAtএবং এর updatedAtবৈশিষ্ট্যগুলি এবং সন্ধান করতে পারি না ।

সুতরাং নীচের লাইনটি, সর্বোপরি আমি চেষ্টা করেছি: একটি নথি দেওয়া আছে contact, কীভাবে এটি উপস্থিত থাকলে তা আপডেট করব, না থাকলে এটি যুক্ত করব?

আপনার সময় জন্য ধন্যবাদ।


কী hooking সম্পর্কে preজন্য save?
শামুন

উত্তর:


427

নকুল এখন এই নেটিভ সঙ্গে সমর্থন findOneAndUpdate (কল MongoDB findAndModify )।

আপসেট = সত্য বিকল্পটি উপস্থিত না থাকলে অবজেক্টটি তৈরি করে। মিথ্যা ডিফল্ট

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

পুরানো সংস্করণগুলিতে মঙ্গুজ এই পদ্ধতিতে এই হুকগুলি সমর্থন করে না:

  • পূর্ব নির্ধারিত
  • setters
  • ভ্যালিডেটর
  • মিডলওয়্যার

17
এটি আপ টু ডেট উত্তর হওয়া উচিত। অন্যান্য বেশিরভাগ দুটি কল বা (আমি বিশ্বাস করি) নেটিভ মংডোব ড্রাইভারের কাছে ফিরে আসি।
হুগি

10
FindOneAndUpdate এ সমস্যাটি হ'ল প্রাক-সঞ্চয়টি কার্যকর করা হবে না।
a77icu5

2
মঙ্গুজ বা মঙ্গোডিবি-তে বাগের মতো শোনাচ্ছে?
পাস্কালিয়াস

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

আমি মঙ্গুজ প্রকল্পের পৃষ্ঠায় একটি সমস্যা তৈরি করেছি যাতে এটি সম্পর্কে তথ্যটি ডক্সে যুক্ত করার অনুরোধ করে।


1
ডকুমেন্টেশন এই মুহুর্তে খারাপ বলে মনে হচ্ছে। আছে: এপিআই দস্তাবেজে কিছু (পৃষ্ঠাতে "আপডেট" এর জন্য অনুসন্ধান করা হয় এরকম দেখায়। MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);এবংMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, fn);
CpILL

কেস ডকুমেন্টের জন্য পাওয়া যায় না, কোন _id ব্যবহার করা হয়? মঙ্গুজ এটি তৈরি করে বা যার বিরুদ্ধে জিজ্ঞাসা করা হয়েছিল?
হায়দার

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
এটি লেখার সময় এটি বৈধ ছিল, আমি আর
মঙ্গোডিবি

5
আপনি যদি সময়ে সময়ে নেটিভ ড্রাইভার ব্যবহার করতে যাচ্ছেন তবে সেটটি ব্যবহার না করা একটি খারাপ অভ্যাস হতে পারে।
আপক্রিক

সন্নিবেশের ক্ষেত্রে কেবলমাত্র নির্দিষ্ট ক্ষেত্রগুলি সেট করতে আপনি $ সেট এবং $ setOnInsert ব্যবহার করতে পারেন
justin.m.c चरण

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 ডিবি কল করে।
আশা করি ভবিষ্যতে একটি মঙ্গুজ বাস্তবায়ন একটি Model.upsertঅনুষ্ঠান নিয়ে হাজির হবে ।


2
এই উদাহরণগুলি একটি ডকুমেন্ট ফর্মের মধ্যে মাল্টি এবং আপসেট বিকল্পগুলি নির্দিষ্ট করতে মঙ্গোডিবি ২.২ এ যুক্ত ইন্টারফেসটি ব্যবহার করে। .. অন্তর্ভুক্ত :: /includes/fact-upsert-m Multi-options.rst ডকুমেন্টেশন এ উল্লেখ করছে, কোথা থেকে যেতে হবে জানি না।
ডোনাল্ড ডেরেক

1
যদিও এটি কাজ করা উচিত, আপনি এখন 2 টি অপারেশন চালাচ্ছেন (সন্ধান করুন, আপডেট করুন) যখন কেবল 1 টি (আপসেট) প্রয়োজন হয়। @ ক্রিক্সিয়ান এটি করার সঠিক উপায় দেখায়।
শ্রদ্ধেডকোড

12
এটি লক্ষণীয় যে এটিই হ'ল একমাত্র উত্তর যা মঙ্গুসের বৈধতা দমন করতে দেয় doc ডক্স অনুসারে , আপনি আপডেট কল করলে বৈধতা পাওয়া যায় না।
টম স্পেন্সার

@ ফিজনুল দেখে মনে হচ্ছে আপনি runValidators: trueকোনও আপডেটের সময় বিকল্পটিতে ম্যানুয়ালি পাস করতে পারবেন: নথিগুলি আপডেট করুন (তবে আপডেট বৈধরা কেবল চালিত $setএবং $unsetঅপারেশন করে)
ড্যানি

আপনার যদি .upsert()সমস্ত মডেলগুলিতে উপলব্ধ হওয়ার প্রয়োজন হয় তবে এটির উপর ভিত্তি করে আমার উত্তরটি দেখুন । stackoverflow.com/a/50208331/1586406
spondbob

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

কেন এটি upvated ছিল না? দুর্দান্ত সমাধান হিসাবে দেখা এবং খুব মার্জিত
ম্যাডোগ্রে

উজ্জ্বল সমাধান, আসলে আমি কীভাবে প্রতিশ্রুতিগুলির নিকটবর্তী হই সে সম্পর্কে আমাকে পুনর্বিবেচনা করিয়েছে।
লাক্স

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প্যারামিটারে রাখতে হবে।

মঙ্গুসের সাথে নথিপত্র সংরক্ষণের জন্য একটি টিউটোরিয়াল এখানে ।


15

এই প্রশ্নের উত্তর দেওয়ার জন্য আমি একটি স্ট্যাকওভারফ্লো অ্যাকাউন্ট তৈরি করেছি। নিরর্থকভাবে আন্তঃস্বত্ত্ব অনুসন্ধান করার পরে আমি নিজেই কিছু লিখেছিলাম। এটি আমি এটি করেছিলাম যাতে এটি কোনও মঙ্গুসের মডেলকে প্রয়োগ করা যায়। হয় এই ফাংশনটি আমদানি করুন বা এটিকে সরাসরি আপনার কোডে যুক্ত করুন যেখানে আপনি আপডেটিং করছেন।

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 ডিবি কল প্রয়োজন হতে পারে তবে আপনি এর সুবিধা পান,

  • আপনার মডেলের বিরুদ্ধে স্কিমা বৈধতা কারণ আপনি .save () ব্যবহার করছেন
  • আপনি আপনার আপডেট কলটিতে ম্যানুয়াল গণনা ছাড়াই গভীরভাবে নেস্টেড অবজেক্টগুলি সজ্জিত করতে পারেন, সুতরাং যদি আপনার মডেল পরিবর্তন হয় তবে আপনাকে আপনার কোড আপডেট করার বিষয়ে চিন্তা করতে হবে না

কেবল মনে রাখবেন যে গন্তব্য অবজেক্টটি সর্বদা উত্সটিকে ওভাররাইড করবে যদিও উত্সটির একটি বিদ্যমান মান রয়েছে

এছাড়াও অ্যারেগুলির জন্য, যদি বিদ্যমান অবজেক্টটি প্রতিস্থাপনের চেয়ে দীর্ঘতর অ্যারে থাকে তবে পুরানো অ্যারের শেষে থাকা মানগুলি থাকবে। পুরো অ্যারেটি উপস্থাপনের একটি সহজ উপায় হ'ল পুরাতন অ্যারেটিকে খালি অ্যারে হিসাবে সেট করার আগে যদি আপনি এটি করতে চান যা হয়।

আপডেট - 01/16/2016 আমি যদি আদিম মানের একটি অ্যারে থাকে তবে এর জন্য আমি একটি অতিরিক্ত শর্ত জুড়েছি, "সেট" ফাংশনটি ব্যবহার না করে মুরগেস অ্যারে আপডেট হয়ে যায় বুঝতে পারে না।


2
কেবলমাত্র এটির জন্য আইকি তৈরির জন্য +1: পি কাশী আমি কেবলমাত্র .save () ব্যবহার করার জন্য আরও 1 + দিতে পারতাম, কারণ অনুসন্ধান ওয়ানঅ্যান্ডআপেট () আমাদের বৈধকরণকারী এবং প্রাক, পোস্ট, ইত্যাদি স্টাফ ব্যবহার করতে অক্ষম করে। ধন্যবাদ, আমি এটিও যাচাই করব
user1576978

দুঃখিত, তবে এটি এখানে কাজ করে না :( আমি কল স্ট্যাকের আকার ছাড়িয়েছি
ইউজার 1576978

লোডাশের কোন সংস্করণ আপনি ব্যবহার করছেন? আমি লোডাশ সংস্করণটি ব্যবহার করছি ২.৪.১ ধন্যবাদ!
অ্যারন মাস্ট

এছাড়াও, আপনি কীভাবে জটিল বস্তুগুলি সংরক্ষণ করছেন? যদি তারা খুব বড় হয় তবে নোড প্রক্রিয়াটি অবজেক্টগুলিকে একীভূত করতে প্রয়োজনীয় পুনরাবৃত্ত কলগুলির সংখ্যা পরিচালনা করতে সক্ষম হতে পারে।
অ্যারন মাস্ট

আমি এটি ব্যবহার করেছি, তবে 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);
});

এই আউটপুটটি আমি প্রথম স্ক্রিপ্টটি চালানোর পরে পেয়েছি:

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

        });
    });

মঙ্গুজে আপডেট পদ্ধতিটি সমাধান করার জন্য এখানে আরও ভাল পদ্ধতি রয়েছে, আপনি আরও তথ্যের জন্য Scotch.io পরীক্ষা করতে পারেন । এটি অবশ্যই আমার জন্য কাজ করেছে !!!


5
এটি ভাবতে ভুল হয় যে এটি মঙ্গোডিবি আপডেট হিসাবে একই কাজ করে। এটি পারমাণবিক নয়।
ভ্যালেন্টিন ওয়েজিলিঙ্ক

1
আমি @ ভ্যালেন্টিনওয়েসিলিঙ্ক উত্তরটি ব্যাক আপ করতে চাই। স্কচের কোডটি পরিষ্কার - তবে আপনি একটি দস্তাবেজ আনছেন এবং তারপরে আপডেট করছেন। এই প্রক্রিয়াটির মাঝামাঝি সময়ে নথিটি পরিবর্তিত হতে পারে।
নিক পাইনেদা

8

২.6-তে একটি বাগ প্রবর্তিত হয়েছে এবং এটি ২.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 ডিবি কল প্রয়োজন তবে আমি একক কলে চেষ্টা করেছিলাম তার চেয়ে অনেক বেশি স্থিতিশীল।

// 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

এই কফিসিপিটি নোডের সাথে আমার জন্য কাজ করে - কৌশলটি হ'ল ক্লায়েন্টের কাছ থেকে প্রেরণ এবং ফিরে আসার সময় _আইডি এর অবজেক্টআইডি মোড়কটি ছিনিয়ে নিয়ে যায় এবং তাই আপডেটের জন্য এটি প্রতিস্থাপন করা প্রয়োজন (যখন কোনও _আইডি সরবরাহ করা হয় না, তখন সংরক্ষণটি সন্নিবেশ করানো হবে এবং যুক্ত হবে এক).

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

মার্টিন কুজডোইভিজ উপরে পোস্ট করেছেন যা উপর ভিত্তি করে। আমি মঙ্গুজ এবং জেসন অবজেক্টের গভীর একত্রীকরণ ব্যবহার করে একটি আপডেট করতে নিম্নলিখিতগুলি ব্যবহার করি। মডেল.স্যাভ () এর সাথে মঙ্গুজে ফাংশন এটি মঙ্গসকে একটি সম্পূর্ণ বৈধতা এমনকি ম্যাসেজের যা জাসনের অন্যান্য মানের উপর নির্ভর করে তা করতে দেয়। এটির জন্য ডিপমার্জ প্যাকেজ https://www.npmjs.com/package/ ডিগ্রিমার প্রয়োজন । তবে এটি খুব হালকা ওজনের প্যাকেজ।

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
নোএসকিউএল ইনজেকশনreq.body পরীক্ষা করার আগে আমি যেমন ছিল তেমন ব্যবহার সম্পর্কে সতর্কতা অবলম্বন করব (দেখুন owasp.org/index.php/Testing_for_NoSQL_inication )।
ট্র্যাভেলিং টেক গাই

1
@ ট্র্যাভেলিংটেকগুই সতর্কতার জন্য ধন্যবাদ আমি এখনও নোড এবং মঙ্গুজে নতুন new ভ্যালিডেটরগুলির সাথে আমার মঙ্গুসের মডেলটি কোনও ইনজেকশন চেষ্টা চালানোর পক্ষে যথেষ্ট হবে না? Model.save ()
ক্রিস Deleo

-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 নাল হয়, আমরা নতুন আইটেম তৈরি করি। অন্যথায়, আপডেটে আপসার্ট ব্যবহার করুন কারণ আপডেট নতুন আইটেম তৈরি করে না।


যদি এটি মঙ্গোতে দুটি কল হয় তবে এটি আসলেই উত্সাহ নয়?
হুগি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.