এটি প্রকৃতপক্ষে http://jira.mongodb.org/browse/SERVER-1243 এ দীর্ঘস্থায়ী ইস্যুটির সাথে সম্পর্কিত যেখানে যেখানে একাধিক চ্যালেঞ্জ রয়েছে একটি পরিষ্কার বাক্য গঠন যা "সমস্ত ক্ষেত্রে" সমর্থন করে যেখানে একাধিক অ্যারে ম্যাচগুলি হয় পাওয়া যায় নি। ইতিমধ্যে বাস্তবে এমন অনেক পদ্ধতি রয়েছে যা বাল্ক অপারেশনের মতো এই সমস্যার সমাধানে "সহায়তা" করে যা এই মূল পোস্টের পরে প্রয়োগ করা হয়েছে।
একটি একক আপডেটের বিবৃতিতে একটি একক ম্যাচযুক্ত অ্যারের উপাদানটির চেয়ে বেশি আপডেট করা এখনও সম্ভব নয়, সুতরাং "মাল্টি" আপডেটের মাধ্যমে আপনি যে সমস্ত আপডেট করতে সক্ষম হবেন সেই একক প্রতিটি নথির জন্য অ্যারেতে কেবল একটি ম্যাথড উপাদান রয়েছে is বিবৃতি।
বর্তমানে সর্বোত্তম সম্ভাব্য সমাধান হ'ল সমস্ত মিলে যাওয়া নথিগুলি সন্ধান এবং লুপ করা এবং বাল্ক আপডেটগুলি অন্ততপক্ষে একক অনুরোধে একক অনুরোধে অনেকগুলি ক্রিয়াকলাপ পাঠানো মঞ্জুরি দেয় sing আপনি .aggregate()
অনুসন্ধানের ফলাফলটিতে ফিরে আসা অ্যারে সামগ্রী হ্রাস করতে optionচ্ছিকভাবে ব্যবহার করতে পারেন কেবল আপডেটের নির্বাচনের শর্তগুলির সাথে মেলে:
db.collection.aggregate([
{ "$match": { "events.handled": 1 } },
{ "$project": {
"events": {
"$setDifference": [
{ "$map": {
"input": "$events",
"as": "event",
"in": {
"$cond": [
{ "$eq": [ "$$event.handled", 1 ] },
"$$el",
false
]
}
}},
[false]
]
}
}}
]).forEach(function(doc) {
doc.events.forEach(function(event) {
bulk.find({ "_id": doc._id, "events.handled": 1 }).updateOne({
"$set": { "events.$.handled": 0 }
});
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
});
});
if ( count % 1000 != 0 )
bulk.execute();
.aggregate()
অংশ সেখানে কাজ করবে যখন সেখানে বিন্যাস বা প্রতিটি উপাদানের জন্য সমস্ত সামগ্রীর জন্য একটি "অনন্য" শনাক্তকারী উপাদান একটি "অনন্য" নিজেই ফর্ম। এটি ম্যাচের জন্য অ্যারে প্রক্রিয়াজাতকরণের জন্য ব্যবহৃত অপারেশন থেকে প্রত্যাবর্তিত $setDifference
কোনও false
মান ফিল্টার করতে ব্যবহৃত "সেট" অপারেটরের কারণে এটি $map
।
যদি আপনার অ্যারে সামগ্রীতে স্বতন্ত্র উপাদান না থাকে তবে আপনি এর সাথে বিকল্প পদ্ধতির চেষ্টা করতে পারেন $redact
:
db.collection.aggregate([
{ "$match": { "events.handled": 1 } },
{ "$redact": {
"$cond": {
"if": {
"$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}}
])
এটির সীমাবদ্ধতা হ'ল যদি "পরিচালিত" আসলে ক্ষেত্রটি অন্য নথির স্তরে উপস্থিত থাকত তবে আপনি সম্ভবত অনিচ্ছুক ফলাফল পেতে চলেছেন তবে ঠিক আছে যেখানে ক্ষেত্রটি কেবলমাত্র একটি নথির পজিশনে প্রদর্শিত হয় এবং এটি একটি সমতা ম্যাচ।
ভবিষ্যতের প্রকাশগুলি (৩.১ মঙ্গোডিবি পোস্ট) লেখার মতো একটি $filter
অপারেশন থাকবে যা সহজ:
db.collection.aggregate([
{ "$match": { "events.handled": 1 } },
{ "$project": {
"events": {
"$filter": {
"input": "$events",
"as": "event",
"cond": { "$eq": [ "$$event.handled", 1 ] }
}
}
}}
])
এবং সমস্ত রিলিজ যা সমর্থন .aggregate()
করে সাথে নিম্নলিখিত পদ্ধতিটি ব্যবহার করতে পারে $unwind
, তবে সেই অপারেটরের ব্যবহার পাইপলাইনে অ্যারে প্রসারণের কারণে এটি নূন্যতম দক্ষ পদ্ধতির তৈরি করে:
db.collection.aggregate([
{ "$match": { "events.handled": 1 } },
{ "$unwind": "$events" },
{ "$match": { "events.handled": 1 } },
{ "$group": {
"_id": "$_id",
"events": { "$push": "$events" }
}}
])
সমস্ত ক্ষেত্রে যেখানে মঙ্গোডিবি সংস্করণ সামগ্রিক আউটপুট থেকে একটি "কার্সর" সমর্থন করে, তবে এটি কেবলমাত্র একটি পদ্ধতির পছন্দ বেছে নেওয়া এবং বাল্ক আপডেটের বিবৃতিগুলি প্রক্রিয়া করার জন্য প্রদর্শিত কোডের একই ব্লকের সাথে ফলাফলগুলি পুনরাবৃত্তি করার বিষয়। সমষ্টিগত আউটপুট থেকে বাল্ক অপারেশন এবং "কার্সার" একই সংস্করণে প্রবর্তিত হয় (মঙ্গোডিবি 2.6) এবং তাই সাধারণত প্রক্রিয়াজাতকরণের জন্য হাতে হাতে কাজ করে।
এমনকি পূর্ববর্তী সংস্করণগুলিতে সবেমাত্র .find()
কার্সারটি ফেরত দেওয়ার জন্য ব্যবহার করা ভাল , এবং .update()
পুনরাবৃত্তির জন্য অ্যারে উপাদানটির সংখ্যার সাথে অ্যারে উপাদানটির সংখ্যার সাথে বিবৃতি প্রয়োগের ক্ষেত্রে ফিল্টার আউট করা উচিত :
db.collection.find({ "events.handled": 1 }).forEach(function(doc){
doc.events.filter(function(event){ return event.handled == 1 }).forEach(function(event){
db.collection.update({ "_id": doc._id },{ "$set": { "events.$.handled": 0 }});
});
});
আপনি যদি "মাল্টি" আপডেটগুলি অবিচ্ছিন্নভাবে নির্ধারণ করে থাকেন বা প্রতিটি মিলিত নথির জন্য একাধিক আপডেট প্রসেসিংয়ের চেয়ে চূড়ান্তভাবে আরও বেশি দক্ষ হিসাবে বিবেচিত হন, তবে আপনি সর্বদা সম্ভাব্য অ্যারে ম্যাচের সর্বাধিক সংখ্যা নির্ধারণ করতে পারেন এবং কেবল "মাল্টি" আপডেট চালিয়ে যেতে পারেন যা অনেকগুলি বার, মূলত অবধি আপডেট করার জন্য আর কোনও নথি নেই।
মঙ্গোডিবি ২.৪ এবং ২.২ সংস্করণগুলির জন্য একটি বৈধ পন্থাও .aggregate()
এই মানটি খুঁজে পেতে ব্যবহার করতে পারে :
var result = db.collection.aggregate([
{ "$match": { "events.handled": 1 } },
{ "$unwind": "$events" },
{ "$match": { "events.handled": 1 } },
{ "$group": {
"_id": "$_id",
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": null,
"count": { "$max": "$count" }
}}
]);
var max = result.result[0].count;
while ( max-- ) {
db.collection.update({ "events.handled": 1},{ "$set": { "events.$.handled": 0 }},{ "multi": true })
}
যাই হোক না কেন, আপডেটের মধ্যে আপনি কিছু করতে চান না এমন কিছু নির্দিষ্ট জিনিস রয়েছে :
অ্যারেটি "একটি শট" আপডেট করবেন না: আপনি যদি মনে করেন কোডে পুরো অ্যারে সামগ্রী আপডেট করতে এবং তারপরে $set
প্রতিটি নথিতে কেবলমাত্র পুরো অ্যারেটি আপডেট করা আরও দক্ষ হতে পারে । এটি প্রক্রিয়াটিকে দ্রুত বলে মনে হতে পারে তবে অ্যারের সামগ্রীটি পড়ার পরে এবং আপডেটটি সম্পাদন করার পরেও কোনও পরিবর্তন হয়নি যে কোনও গ্যারান্টি নেই। যদিও $set
এটি এখনও একটি পারমাণবিক অপারেটর, এটি কেবল অ্যারেটিকে এটি "সঠিকভাবে" কী বলে মনে করে তা আপডেট করবে এবং এভাবে পঠন এবং লেখার মধ্যবর্তী যে কোনও পরিবর্তনগুলি ওভাররাইটের সম্ভাবনা রয়েছে।
আপডেট করার জন্য সূচকের মানগুলি গণনা করবেন না: যেখানে "ওয়ান শট" পদ্ধতির অনুরূপ আপনি কেবল সেই অবস্থান 0
এবং অবস্থানের 2
(এবং আরও কিছু) কাজ করেন এবং এগুলিকে আপডেট এবং কোড করার জন্য উপাদানগুলি হয় এবং শেষ অবধি:
{ "$set": {
"events.0.handled": 0,
"events.2.handled": 0
}}
আবার সমস্যাটি হ'ল "অনুমান" যে নথিটি পড়ার সময় সেই সূচকগুলির মানগুলি আপডেটের সময় তম অ্যারে একই সূচক মান values যদি নতুন আইটেমগুলি অ্যারেতে এমনভাবে যুক্ত করা হয় যাতে ক্রম পরিবর্তন হয় তবে সেই অবস্থানগুলি আর কার্যকর হবে না এবং ভুল আইটেমগুলি আসলে আপডেট হয়।
সুতরাং একক আপডেটের বিবৃতিতে একাধিক মিলিত অ্যারে উপাদানগুলিকে প্রক্রিয়াজাতকরণের মঞ্জুরি দেওয়ার জন্য যুক্তিসঙ্গত সংশ্লেষ না হওয়া পর্যন্ত মূল পদ্ধতির হয় হয় প্রতিটি মিলিত অ্যারে উপাদানকে একটি indvidual বিবৃতিতে (আদর্শভাবে বাল্কে) আপডেট করা বা মূলত সর্বাধিক অ্যারে উপাদানগুলি কাজ করা আর কোনও পরিবর্তিত ফলাফল না ফেরানো পর্যন্ত আপডেট করা বা আপডেট করা অবধি to যে কোনও হারে, আপনার উচিত "সর্বদা" ম্যাচ করা অ্যারে উপাদান সম্পর্কিত অবস্থানগত$
আপডেটগুলি প্রক্রিয়াকরণ করা উচিত , এমনকি যদি সে বিবৃতিতে কেবল একটি উপাদান আপডেট করে।
বাল্ক অপারেশনগুলি আসলে "একাধিক অপারেশন" হিসাবে কাজ করে এমন কোনও অপারেশন প্রক্রিয়াজাতকরণের "সাধারণীকরণ" সমাধান, এবং যেহেতু এটির জন্য একই মান সহ একাধিক অ্যারে উপাদানগুলি কেবল আপডেট করার চেয়ে আরও বেশি অ্যাপ্লিকেশন রয়েছে, তবে অবশ্যই এটি প্রয়োগ করা হয়েছে ইতিমধ্যে, এবং এটি বর্তমানে এই সমস্যাটি সমাধানের জন্য সর্বোত্তম পন্থা।