মঙ্গোডিবি পারমাণবিক "FindOrCreate": সন্ধান করুন, অস্তিত্বহীন থাকলে sertোকান, তবে আপডেট করবেন না


114

শিরোনাম অনুসারে, আমি _id দ্বারা একটি দস্তাবেজের সন্ধান (এক) সম্পাদন করতে চাই এবং যদি এটি উপস্থিত না থাকে তবে এটি তৈরি করেছে, তবে এটি সন্ধান পেয়েছিল বা তৈরি হয়েছিল, তা কি কলব্যাকে ফিরে এসেছে?

আমি এটি আপডেট থাকলে এটি আপডেট করতে চাই না, কারণ আমি খুঁজে পেয়েছি এবং মোডেফিডে করে। এ সম্পর্কিত স্ট্যাকওভারফ্লোতে আমি আরও অনেক প্রশ্ন দেখেছি কিন্তু আবারও কোনও কিছুর আপডেট করতে চাই না।

(বিদ্যমান নেই) তৈরি করে আমি নিশ্চিত নই, এটিই যে আপডেটের কথা বলছেন তা আসলেই এত বিভ্রান্তিকর :(

উত্তর:


192

মঙ্গোডিবি ২.৪ দিয়ে শুরু করে, পারমাণবিক findOrCreateজাতীয় ক্রিয়াকলাপের জন্য আর কোনও অনন্য সূচকের উপর (বা অন্য কোনও কাজের ভিত্তিতে) নির্ভর করার প্রয়োজন নেই ।

এই ধন্যবাদ অপারেটর 2.4 নতুন, যা আপনি আপডেট যা শুধুমাত্র ঘটা উচিত ডকুমেন্ট ঢোকাতে নির্দিষ্ট করার অনুমতি দেয়।$setOnInsert

এটি, upsertবিকল্পটির সাথে মিলিত হওয়ার অর্থ আপনি findAndModifyপারমাণবিক-জাতীয় findOrCreateক্রিয়াকলাপটি অর্জন করতে ব্যবহার করতে পারেন ।

db.collection.findAndModify({
  query: { _id: "some potentially existing id" },
  update: {
    $setOnInsert: { foo: "bar" }
  },
  new: true,   // return new doc if one is upserted
  upsert: true // insert the document if it does not exist
})

হিসাবে $setOnInsertশুধুমাত্র দস্তাবেজ inserted হওয়ার প্রভাবিত করে, যদি একটি বিদ্যমান দস্তাবেজ পাওয়া যায়, কোন পরিবর্তন ঘটবে। যদি কোনও দস্তাবেজ উপস্থিত না থাকে তবে এটি নির্দিষ্ট _ আইডের সাথে একটি উপস্থাপন করবে, তবে কেবল সন্নিবেশ সেটটি সম্পাদন করবে। উভয় ক্ষেত্রেই নথিটি ফেরত দেওয়া হয়।


3
@ গ্যাঙ্ক আপনি যদি নং সিনট্যাক্সের জন্য মঙ্গোদব নেটিভ ড্রাইভার ব্যবহার করেন তবে এটি আরও পছন্দ হতে পারে collection.findAndModify({_id:'theId'}, <your sort opts>, {$setOnInsert:{foo: 'bar'}}, {new:true, upsert:true}, callback)দস্তাবেজগুলি
1311407

7
ডকুমেন্টটি আপডেট হয়েছে বা inোকানো হয়েছে কিনা তা জানার কোনও উপায় আছে?
নিয়তি

3
আপনি যদি উপরে জিজ্ঞাসা করতে চান যে উপরের ক্যোয়ারী ( db.collection.findAndModify({query: {_id: "some potentially existing id"}, update: {$setOnInsert: {foo: "bar"}}, new: true, upsert: true})) সন্নিবেশ করানো (উপস্থাপন করা) কোনও দস্তাবেজ সম্পাদনা করেছে, আপনার ব্যবহার বিবেচনা করা উচিত db.collection.updateOne({_id: "some potentially existing id"}, {$setOnInsert: {foo: "bar"}}, {upsert: true}){"acknowledged": true, "matchedCount": 0, "modifiedCount": 0, "upsertedId": ObjectId("for newly inserted one")}ডকটি sertedোকানো {"acknowledged": true, "matchedCount": 1, "modifiedCount": 0}হলে, ডকটি ইতিমধ্যে উপস্থিত থাকলে এটি ফিরে আসে ।
Ван

8
মনে হয় findOneAndUpdate, findOneAndReplaceবাfindOneAndDelete
রওশন সামান্দ্রভ

5
যদিও এখানে অবশ্যই সাবধান হওয়া দরকার। এটি কেবলমাত্র তখনই কাজ করে যদি ফাইন্ডঅ্যান্ডমডিফাইটি / ফাইন্ডঅনঅ্যাপআপেট / আপডেটঅন এর নির্বাচক এককভাবে _id দ্বারা একটি দস্তাবেজ সনাক্ত করে। অন্যথায় উপস্থাপনাটি সার্ভারে একটি ক্যোয়ারিতে এবং একটি আপডেট / সন্নিবেশে বিভক্ত হয়। আপডেটটি এখনও পরমাণু হবে। তবে ক্যোয়ারী এবং আপডেট একসাথে পারমাণবিকভাবে কার্যকর করা হবে না।
আনন

14

ড্রাইভার সংস্করণ> 2

সর্বশেষ ড্রাইভার (> সংস্করণ 2) ব্যবহার , আপনি ব্যবহার করব findOneAndUpdate যেমন findAndModifyঅবচিত করা হয়েছিল। নতুন পদ্ধতিতে 3 টি আর্গুমেন্ট গ্রহণ করা হয়, এটি filter, updateঅবজেক্টটি (এতে আপনার ডিফল্ট বৈশিষ্ট্য রয়েছে যা একটি নতুন অবজেক্টের জন্য সন্নিবেশ করা উচিত) এবং optionsযেখানে আপনাকে উপস্থাপন অপারেশন নির্দিষ্ট করতে হবে।

প্রতিশ্রুতি বাক্য গঠন ব্যবহার করে, এটি দেখতে এরকম দেখাচ্ছে:

const result = await collection.findOneAndUpdate(
  { _id: new ObjectId(id) },
  {
    $setOnInsert: { foo: "bar" },
  },
  {
    returnOriginal: false,
    upsert: true,
  }
);

const newOrUpdatedDocument = result.value;

ধন্যবাদ, আমার মনে করা returnOriginalউচিত returnNewDocument- ডকস.মঙ্গডবি.com
ডমিনিক

কিছু নয়, নোড ড্রাইভার এটিকে অন্যভাবে প্রয়োগ করেছে এবং আপনার উত্তরটি সঠিক
ডমিনিক

6

এটি কিছুটা নোংরা, তবে আপনি এটি সন্নিবেশ করতে পারেন।

নিশ্চিত হয়ে নিন যে কীটির কোনও অনন্য সূচক রয়েছে (যদি আপনি _id এটি ঠিক করেন তবে এটি ইতিমধ্যে অনন্য)।

এইভাবে যদি উপাদানটি ইতিমধ্যে উপস্থিত থাকে তবে এটি আপনাকে ধরতে পারে এমন একটি ব্যতিক্রম ফিরিয়ে দেবে।

এটি উপস্থিত না থাকলে নতুন দস্তাবেজ .োকানো হবে।

আপডেট হয়েছে: মঙ্গোডিবি ডকুমেন্টেশনে এই কৌশলটির বিশদ ব্যাখ্যা


ঠিক আছে, একটি ভাল ধারণা thats, কিন্তু প্রাক বিদ্যমান বিদ্যমান জন্য এটি একটি ত্রুটি ফিরে আসবে কিন্তু মান নিজেই না, অধিকার?
ডিসিপল

3
এটি আসলে অপারেশনের বিচ্ছিন্ন সিকোয়েন্স জন্য প্রস্তাবিত সমাধান এক (এটি তারপর যদি না পেয়ে সম্ভবতঃ তৈরি করুন) docs.mongodb.org/manual/tutorial/isolate-sequence-of-operations
numbers1311407

@ ডিসিপপল আপনি যদি পারমাণবিক ক্রিয়াকলাপের সেট করতে চান তবে আপনার প্রথমে ডকুমেন্টটি লক করা উচিত, তারপরে এটি পরিবর্তন করুন এবং শেষে এটি প্রকাশ করা উচিত। এর জন্য আরও প্রশ্নের প্রয়োজন হবে তবে আপনি সেরা কেস দৃশ্যের জন্য অনুকূল হতে পারেন এবং বেশিরভাগ সময় কেবল 1-2 টি ক্যোয়ারী করতে পারেন। দেখুন: ডকস.মঙ্গোদবি.আর
ম্যানুয়াল

1

আমি যা করেছি তা এখানে (রুবি মঙ্গোডিবি ড্রাইভার):

$db[:tags].update_one({:tag => 'flat'}, {'$set' => {:tag => 'earth' }}, { :upsert => true })}

এটি উপস্থিত থাকলে এটি আপডেট করবে এবং এটি না থাকলে এটি সন্নিবেশ করবে।

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