মংডোবিতে একাধিক অ্যারে উপাদানগুলি কীভাবে আপডেট করবেন


181

আমার কাছে একটি মঙ্গো নথি রয়েছে যা উপাদানগুলির একটি অ্যারে ধারণ করে।

আমি .handledঅ্যারে যেখানে সমস্ত .profileXX এর সমস্ত অবজেক্টের বৈশিষ্ট্য পুনরায় সেট করতে চাই =

দস্তাবেজটি নিম্নলিখিত ফর্মটিতে রয়েছে:

{
    "_id": ObjectId("4d2d8deff4e6c1d71fc29a07"),
    "user_id": "714638ba-2e08-2168-2b99-00002f3d43c0",
    "events": [{
            "handled": 1,
            "profile": 10,
            "data": "....."
        } {
            "handled": 1,
            "profile": 10,
            "data": "....."
        } {
            "handled": 1,
            "profile": 20,
            "data": "....."
        }
        ...
    ]
}

সুতরাং, আমি নিম্নলিখিত চেষ্টা করেছিলাম:

.update({"events.profile":10},{$set:{"events.$.handled":0}},false,true)

তবে এটি প্রতিটি নথিতে প্রথম মিলিত অ্যারে উপাদান আপডেট করে । (এটি $ এর জন্য নির্ধারিত আচরণ - অবস্থানগত অপারেটর ))

আমি কীভাবে সমস্ত মিলিত অ্যারে উপাদানগুলি আপডেট করতে পারি ?


2
একটি উপসেট বা সমস্ত অ্যারে আইটেম আপডেট করা মঙ্গডবি ৩.6-তে যুক্ত করা হয়েছে: ডকস.মঙ্গডব.com
জাপ

অ্যারে ফিল্টারগুলি পরীক্ষা করে দেখুন এবং আপডেটটি দক্ষ করতে কোন কোয়েরিটি ব্যবহার করবেন তা বিবেচনা করুন। নীল লুনের উত্তরটি দেখুন: stackoverflow.com/a/46054172/337401
জাপ

আমার উত্তরটি যাচাই করুন
উকডেমির

উত্তর:


111

এই মুহুর্তে অ্যারেতে সমস্ত আইটেম আপডেট করার জন্য পজিশনাল অপারেটরটি ব্যবহার করা সম্ভব নয়। JIRA দেখুন http://jira.mongodb.org/browse/SERVER-1243

আপনার চারপাশের কাজ হিসাবে:

  • প্রতিটি আইটেম পৃথকভাবে আপডেট করুন (ইভেন্ট.0.হ্যান্ডলড ইভেন্টস 1. হ্যান্ডেলড ...) বা ...
  • দস্তাবেজটি পড়ুন, সম্পাদনাগুলি ম্যানুয়ালি করুন এবং এটি পুরানোটির পরিবর্তে সংরক্ষণ করুন ( আপনি যদি পারমাণবিক আপডেট নিশ্চিত করতে চান তবে "বর্তমানের আপডেট করুন" দেখুন )

15
আপনার যদি একই সমস্যা হয় তবে এই ইস্যুটির জন্য ভোট দিন - jira.mongodb.org/browse/SERVER-1243
লিয়োরএইচ

আমি আসলে পড়ার নথি পছন্দ করি এবং পদ্ধতির সংরক্ষণ করি approach তবে আমি মোঙ্গোর আগে কাউচটি ব্যবহার করেছি যাতে এ পদ্ধতিকে আরও স্বাভাবিক বলে মনে হয় যেহেতু কাউচের জন্য কোনও কোয়েরি এপিআই নেই, পুরো নথির জন্য কেবলমাত্র একটি রিস্টিক এপিআই
আদম

1
এই উভয় পদ্ধতির জন্য যথেষ্ট পরিমাণে স্মৃতি দরকার, তাই না? আপডেট করার জন্য যদি এমন অনেকগুলি নথি থাকে যা অনুসন্ধান করতে হয় এবং তাদের সমস্ত (বা নেস্টেড অ্যারেগুলি) লোড করতে হয় ... + যদি এটি অবিচ্ছিন্নভাবে করতে হয় তবে বাস্তবায়ন করতে কিছুটা ঝামেলাও হয় ...
আইএক্সএক্স

12
সমস্ত প্রযুক্তিগত সমস্যাগুলি বাদ দিয়ে, এটি বিস্ময়কর যে এই বৈশিষ্ট্যটি মঙ্গোডিবিতে উপলব্ধ নয়। এই সীমাবদ্ধতা ডেটাবেস স্কিমা কাস্টমাইজ করা থেকে অনেক স্বাধীনতা হরণ করে।
সুং চ

5
নীল লুন স্ট্যাকওভারফ্লো. com/ a/ 46054172/ 337401 সংস্করণ 3.6 এর জন্য এর উত্তর দিয়েছে। যেহেতু এটি একটি জনপ্রিয় প্রশ্ন তাই নীল লুনের উত্তরের রেফারেল সহ এই স্বীকৃত উত্তরটি আপডেট করার পক্ষে এটি উপযুক্ত।
জাপ

71

মঙ্গোডিবি ৩.6 প্রকাশের সাথে (এবং মোঙ্গোডিবি ৩.৩.১২ থেকে বিকাশ শাখায় উপলব্ধ) আপনি এখন একক অনুরোধে একাধিক অ্যারে উপাদান আপডেট করতে পারবেন।

এটি এই সংস্করণে প্রদর্শিত ফিল্টারড অবস্থানগত$[<identifier>] আপডেট অপারেটর সিনট্যাক্স ব্যবহার করে :

db.collection.update(
  { "events.profile":10 },
  { "$set": { "events.$[elem].handled": 0 } },
  { "arrayFilters": [{ "elem.profile": 10 }], "multi": true }
)

"arrayFilters"জন্য বিকল্পগুলি প্রেরণ যেমন .update()বা এমনকি .updateOne(), .updateMany(), .findOneAndUpdate()বা .bulkWrite()পন্থা উল্লেখ করে অবস্থার আপডেট বিবৃতি দেওয়া আইডেন্টিফায়ার উপর মেলে। প্রদত্ত শর্তের সাথে মেলে এমন কোনও উপাদান আপডেট করা হবে।

উল্লেখ করে যে "multi"প্রশ্নের প্রসঙ্গে প্রদত্ত হিসাবে প্রত্যাশায় ব্যবহৃত হয়েছিল যে এটি "একাধিক উপাদানকে আপডেট করবে" তবে এটি ছিল না এবং এখনও তা নয়। এটির ব্যবহার এখানে "একাধিক নথি" হিসাবে প্রযোজ্য যেমনটি সর্বদা হয়ে থাকে বা এখন অন্যথায় .updateMany()আধুনিক এপিআই সংস্করণগুলির বাধ্যতামূলক সেটিং হিসাবে নির্দিষ্ট করা হয়েছে ।

দ্রষ্টব্য কিছুটা ব্যঙ্গাত্মকভাবে, যেহেতু এটি "বিকল্পগুলি" যুক্তিটিতে নির্দিষ্ট করা আছে.update() এবং পদ্ধতিগুলির তাই সিনট্যাক্সটি সাম্প্রতিক সমস্ত প্রকাশিত ড্রাইভার সংস্করণের সাথে সামঞ্জস্যপূর্ণ।

তবে এটি mongoশেলের ক্ষেত্রে সত্য নয় , যেহেতু পদ্ধতিটি সেখানে প্রয়োগ করা হয়েছে ("ব্যাকগ্রাউন্ড সামঞ্জস্যের জন্য উপহাসের সাথে") arrayFiltersআর্গুমেন্টটি কোনও অভ্যন্তরীণ পদ্ধতি দ্বারা স্বীকৃত এবং অপসারণ করা হয়নি যা "পশ্চাদপদ সামঞ্জস্যতা" সরবরাহ করার জন্য বিকল্পগুলি পার্স করে দেয় মঙ্গোডিবি সার্ভার সংস্করণ এবং একটি "লিগ্যাসি" .update()এপিআই কল সিনট্যাক্স।

সুতরাং আপনি যদি mongoশেল বা অন্যান্য "শেল ভিত্তিক" পণ্যগুলিতে (উল্লেখযোগ্যভাবে রোবো 3 টি) কমান্ডটি ব্যবহার করতে চান তবে আপনার বিকাশ শাখা বা 3.6 বা ততোধিক প্রোডাকশন রিলিজের একটি নতুন সংস্করণ প্রয়োজন।

এছাড়াও positional all $[]"একাধিক অ্যারে উপাদানগুলি" আপডেট করে তবে নির্দিষ্ট শর্তাদি প্রয়োগ না করে এবং অ্যারের সমস্ত উপাদানগুলিতে প্রয়োগ হয় যেখানে এটি পছন্দসই কর্ম।

এই নতুন পজিশনাল অপারেটরগুলি কীভাবে "নেস্টেড" অ্যারে স্ট্রাকচারগুলিতে প্রয়োগ করে, যেখানে "অ্যারেগুলি অন্য অ্যারেতে রয়েছে" তার জন্য নেস্টেড অ্যারে আপডেট করে দেখুন ।

গুরুত্বপূর্ণ - "পূর্ববর্তী সংস্করণগুলি" থেকে আপগ্রেড হওয়া ইনস্টলেশনগুলি মঙ্গোডিবি বৈশিষ্ট্যগুলি সক্ষম করে না, যা বিবৃতিগুলিকে ব্যর্থও করতে পারে। আপনার আপগ্রেড প্রক্রিয়াটি সূচি আপগ্রেডগুলি এবং তারপরে চালানোর মতো বিশদ সহ সম্পূর্ণ হয়েছে তা নিশ্চিত করা উচিত

   db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )

বা আপনার ইনস্টলড সংস্করণে প্রযোজ্য উচ্চতর সংস্করণ। উদাহরণস্বরূপ "4.0"সংস্করণ 4 এবং পরবর্তী সময়ে। এটি নতুন অবস্থানগত আপডেট অপারেটর এবং অন্যান্যদের মতো বৈশিষ্ট্যগুলিকে সক্ষম করেছে। আপনি এটি দিয়েও পরীক্ষা করতে পারেন:

   db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

বর্তমান সেটিংটি ফিরিয়ে দিতে


9
গৃহীত উত্তর আপডেট করা উচিত এবং এই উত্তর উল্লেখ করুন।
জাপ


1
এটা সঠিক। নোট করুন যে রোবো মঙ্গো arrayFiltersএখনও সমর্থন করে না , তাই সিএলআইয়ের মাধ্যমে আপডেট চলছে। stackoverflow.com/questions/48322834/...
drlff

আপনাকে ধন্যবাদ, নীল, বিশেষত গুরুত্বপূর্ণ বিভাগের জন্য, আমার যা ঠিক দরকার ছিল
জানফাবিয়ান

এই কোডটি পিমোঙ্গোতে ERROR প্রদান করে। ত্রুটি ত্রুটি: প্রকারের ত্রুটি বাড়াতে হবে ("% s অবশ্যই সত্য বা মিথ্যা"% (বিকল্প,)) প্রকারের ত্রুটি: উপস্থাপনাটি সত্য বা মিথ্যা হতে হবে
ভগিফ

67

আমার জন্য যা কাজ করেছিল তা হ'ল:

db.collection.find({ _id: ObjectId('4d2d8deff4e6c1d71fc29a07') })
  .forEach(function (doc) {
    doc.events.forEach(function (event) {
      if (event.profile === 10) {
        event.handled=0;
      }
    });
    db.collection.save(doc);
  });

আমি মনে করি এটি মঙ্গো newbies এবং JQuery এবং বন্ধুদের সাথে পরিচিত যে কোনও ব্যক্তির পক্ষে আরও পরিষ্কার।


আমি ব্যবহার করছি db.posts.find({ 'permalink':permalink }).forEach( function(doc) {...এবং আমি পাচ্ছিOops.. TypeError: Object # has no method 'forEach'
স্কুইর্ল

3
@ স্পাইরাল কি মংডোব সংস্করণ পুরানো হতে পারে? কার্সারে প্রতিটি ফাংশনটির জন্য কীভাবে আবেদন করতে হবে সে সম্পর্কে ডকটি পরিষ্কার but docs.mongodb.org/manual/references/method/cursor.forEach
ড্যানিয়েল সেরেসেডো

@ স্পাইরল চেষ্টা করুনdb.posts.find(...).toArray().forEach(...)
মারমোর

আমরা কি ব্যবহার না করে এটি করতে পারি না Javascript? আমি জাভাস্ক্রিপ্ট এপিআই ব্যবহার না করে সরাসরি একটি মঙ্গো শেল থেকে এই আপডেটটি সম্পাদন করতে চাই।
মেলিওডাস

1
আপনি কি জাভা বা স্প্রিং-ডেটা-মঙ্গোদব দিয়ে মঙ্গোদব ড্রাইভারটিতে এই ক্যোয়ারীটি লিখতে পারেন? ধন্যবাদ, ক্রিস
চিকু

18

এটি একটি লুপের সাহায্যেও সম্পন্ন হতে পারে যা এখনও কোনও নথি রয়ে গেছে যা এখনও সাবডোকমেন্টস আপডেট হয়নি তা পরীক্ষা করে দেখুন। এই পদ্ধতিটি আপনার আপডেটগুলির পারমাণবিকতা সংরক্ষণ করে (যা এখানে অন্যান্য সমাধানগুলির মধ্যে অনেকেই দেয় না)।

var query = {
    events: {
        $elemMatch: {
            profile: 10,
            handled: { $ne: 0 }
        }
    }
};

while (db.yourCollection.find(query).count() > 0) {
    db.yourCollection.update(
        query,
        { $set: { "events.$.handled": 0 } },
        { multi: true }
    );
}

লুপটি কার্যকর হওয়ার সময়টি আপনার সংগ্রহে থাকা কোনও নথির মধ্যে profile10 এর handledসমান এবং 0 এর সমান নয় সহ সর্বাধিক সংখ্যার সাব -ডকুমেন্টের সমান হবে। সুতরাং আপনার সংগ্রহে যদি 100 টি ডকুমেন্ট থাকে এবং সেগুলির একটিতে তিনটি সাব-ডকুমেন্ট মেলেquery ডকুমেন্ট থাকে যা মিলে এবং অন্য সমস্ত নথিতে কম মিলের সাব-ডকুমেন্ট থাকে, লুপটি তিনবার কার্যকর হবে।

এই পদ্ধতিটি অন্য ডেটা ক্লোবারিংয়ের বিপদ এড়িয়ে চলে যা এই স্ক্রিপ্টটি কার্যকর করার সময় অন্য কোনও প্রক্রিয়া দ্বারা আপডেট করা যেতে পারে। এটি ক্লায়েন্ট এবং সার্ভারের মধ্যে স্থানান্তরিত হওয়া ডেটার পরিমাণও হ্রাস করে।


13

এটি প্রকৃতপক্ষে 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 })
}

যাই হোক না কেন, আপডেটের মধ্যে আপনি কিছু করতে চান না এমন কিছু নির্দিষ্ট জিনিস রয়েছে :

  1. অ্যারেটি "একটি শট" আপডেট করবেন না: আপনি যদি মনে করেন কোডে পুরো অ্যারে সামগ্রী আপডেট করতে এবং তারপরে $setপ্রতিটি নথিতে কেবলমাত্র পুরো অ্যারেটি আপডেট করা আরও দক্ষ হতে পারে । এটি প্রক্রিয়াটিকে দ্রুত বলে মনে হতে পারে তবে অ্যারের সামগ্রীটি পড়ার পরে এবং আপডেটটি সম্পাদন করার পরেও কোনও পরিবর্তন হয়নি যে কোনও গ্যারান্টি নেই। যদিও $setএটি এখনও একটি পারমাণবিক অপারেটর, এটি কেবল অ্যারেটিকে এটি "সঠিকভাবে" কী বলে মনে করে তা আপডেট করবে এবং এভাবে পঠন এবং লেখার মধ্যবর্তী যে কোনও পরিবর্তনগুলি ওভাররাইটের সম্ভাবনা রয়েছে।

  2. আপডেট করার জন্য সূচকের মানগুলি গণনা করবেন না: যেখানে "ওয়ান শট" পদ্ধতির অনুরূপ আপনি কেবল সেই অবস্থান 0এবং অবস্থানের 2(এবং আরও কিছু) কাজ করেন এবং এগুলিকে আপডেট এবং কোড করার জন্য উপাদানগুলি হয় এবং শেষ অবধি:

    { "$set": {
        "events.0.handled": 0,
        "events.2.handled": 0
    }}

    আবার সমস্যাটি হ'ল "অনুমান" যে নথিটি পড়ার সময় সেই সূচকগুলির মানগুলি আপডেটের সময় তম অ্যারে একই সূচক মান values যদি নতুন আইটেমগুলি অ্যারেতে এমনভাবে যুক্ত করা হয় যাতে ক্রম পরিবর্তন হয় তবে সেই অবস্থানগুলি আর কার্যকর হবে না এবং ভুল আইটেমগুলি আসলে আপডেট হয়।

সুতরাং একক আপডেটের বিবৃতিতে একাধিক মিলিত অ্যারে উপাদানগুলিকে প্রক্রিয়াজাতকরণের মঞ্জুরি দেওয়ার জন্য যুক্তিসঙ্গত সংশ্লেষ না হওয়া পর্যন্ত মূল পদ্ধতির হয় হয় প্রতিটি মিলিত অ্যারে উপাদানকে একটি indvidual বিবৃতিতে (আদর্শভাবে বাল্কে) আপডেট করা বা মূলত সর্বাধিক অ্যারে উপাদানগুলি কাজ করা আর কোনও পরিবর্তিত ফলাফল না ফেরানো পর্যন্ত আপডেট করা বা আপডেট করা অবধি to যে কোনও হারে, আপনার উচিত "সর্বদা" ম্যাচ করা অ্যারে উপাদান সম্পর্কিত অবস্থানগত$ আপডেটগুলি প্রক্রিয়াকরণ করা উচিত , এমনকি যদি সে বিবৃতিতে কেবল একটি উপাদান আপডেট করে।

বাল্ক অপারেশনগুলি আসলে "একাধিক অপারেশন" হিসাবে কাজ করে এমন কোনও অপারেশন প্রক্রিয়াজাতকরণের "সাধারণীকরণ" সমাধান, এবং যেহেতু এটির জন্য একই মান সহ একাধিক অ্যারে উপাদানগুলি কেবল আপডেট করার চেয়ে আরও বেশি অ্যাপ্লিকেশন রয়েছে, তবে অবশ্যই এটি প্রয়োগ করা হয়েছে ইতিমধ্যে, এবং এটি বর্তমানে এই সমস্যাটি সমাধানের জন্য সর্বোত্তম পন্থা।


8

আমি এখনও অবাক হয়েছি মঙ্গোতে এখনও এটি সম্বোধন করা হয়নি। উপ-অ্যারেগুলির সাথে কাজ করার সময় সামগ্রিকভাবে মঙ্গো দুর্দান্ত বলে মনে হয় না। আপনি উদাহরণস্বরূপ কেবলমাত্র সাব-অ্যারে গণনা করতে পারবেন না।

আমি জাভিয়ের প্রথম সমাধানটি ব্যবহার করেছি। ইভেন্টগুলিতে অ্যারেটি পড়ুন তারপরে লুপ করুন এবং সেট এক্সপকে তৈরি করুন:

var set = {}, i, l;
for(i=0,l=events.length;i<l;i++) {
  if(events[i].profile == 10) {
    set['events.' + i + '.handled'] = 0;
  }
}

.update(objId, {$set:set});

শর্তসাপেক্ষ পরীক্ষার জন্য কলব্যাক ব্যবহার করে এটি কোনও ফাংশনে বিমূর্ত করা যেতে পারে


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

9
এটি কোনও নিরাপদ সমাধান নয়। আপনি আপডেট চালনার সময় যদি কোনও রেকর্ড যুক্ত হয়, আপনি আপনার ডেটাটিকে দূষিত করবেন।
Merc

4

আমি সি # 3.6 এর জন্য সর্বশেষতম ড্রাইভারটি ব্যবহার করে এর সমাধান খুঁজছি এবং আমি শেষ পর্যন্ত স্থির করে ফেললাম। এখানে কীটি "$ []" ব্যবহার করছে যা মঙ্গোডিবি অনুসারে সংস্করণ ৩.6 হিসাবে নতুন। Https://docs.mongodb.com/manual/references/operator/update/positional-all/#up দেখুন আরও তথ্যের জন্য এস []

কোডটি এখানে:

{
   var filter = Builders<Scene>.Filter.Where(i => i.ID != null);
   var update = Builders<Scene>.Update.Unset("area.$[].discoveredBy");
   var result = collection.UpdateMany(filter, update, new UpdateOptions { IsUpsert = true});
}

আরও প্রসঙ্গে এখানে আমার মূল পোস্টটি দেখুন: মংগডিবি সি # ড্রাইভার ব্যবহার করে সমস্ত নথি থেকে অ্যারের উপাদান সরান


4

থ্রেডটি খুব পুরানো, তবে আমি এখানে উত্তরটি খুঁজতে এসেছি তাই নতুন সমাধান সরবরাহ করছি।

মঙ্গোডিবি সংস্করণ 3.6+ এর সাথে, এখন অ্যারেতে সমস্ত আইটেম আপডেট করার জন্য পজিশনাল অপারেটরটি ব্যবহার করা সম্ভব। অফিসিয়াল ডকুমেন্টেশন দেখুন এখানে

নিম্নলিখিত জিজ্ঞাসা এখানে জিজ্ঞাসিত প্রশ্নের জন্য কাজ করবে। আমি জাভা-মঙ্গোডিবি ড্রাইভারের সাথেও যাচাই করেছি এবং এটি সফলভাবে কাজ করে।

.update(   // or updateMany directly, removing the flag for 'multi'
   {"events.profile":10},
   {$set:{"events.$[].handled":0}},  // notice the empty brackets after '$' opearor
   false,
   true
)

আশা করি এটি আমার মতো কাউকে সহায়তা করবে।


1

আমি নিম্নলিখিত এবং এর কাজ সূক্ষ্ম চেষ্টা করেছিলাম।

.update({'events.profile': 10}, { '$set': {'events.$.handled': 0 }},{ safe: true, multi:true }, callback function);

নোডেজের ক্ষেত্রে // কলব্যাক ফাংশন


এই কোডটি অ্যারেতে প্রথম মিলিত আইটেমটি আপডেট করে। ভুল উত্তর.
হ্যামলেট

এটি v2.6 এর জন্য কাজ করে। আপনি একটি পুরানো সংস্করণ হতে পারে? এখানে এর ডক ডকস.মংগডব.ম্যানুয়াল
জিয়ালিন জোউ

1

আপনি মঙ্গোডিবিতে সমস্ত উপাদান আপডেট করতে পারেন

db.collectioname.updateOne(
{ "key": /vikas/i },
{ $set: { 
 "arr.$[].status" : "completed"
} }
)

এটি "অ্যারে" অ্যারেতে "সমাপ্ত" থেকে সমস্ত "স্থিতি" মান আপডেট করবে

যদি কেবল একটি ডকুমেন্ট থাকে

db.collectioname.updateOne(
 { key:"someunique", "arr.key": "myuniq" },
 { $set: { 
   "arr.$.status" : "completed", 
   "arr.$.msgs":  {
                "result" : ""
        }
   
 } }
)

তবে যদি না হয় এবং আপনি অ্যারেতে সমস্ত নথী আপডেট করতে চান না তবে আপনাকে উপাদানটির মাধ্যমে এবং যদি ব্লকের ভিতরে লুপ করতে হবে

db.collectioname.find({findCriteria })
  .forEach(function (doc) {
    doc.arr.forEach(function (singlearr) {
      if (singlearr check) {
        singlearr.handled =0
      }
    });
    db.collection.save(doc);
  });

0

প্রকৃতপক্ষে, সংরক্ষণ আদেশটি কেবলমাত্র নথি ক্লাসের উদাহরণে on যে পদ্ধতি এবং গুণাবলী অনেক আছে। সুতরাং কাজের চাপ কমাতে আপনি পাতলা () ফাংশনটি ব্যবহার করতে পারেন । এখানে উল্লেখ করুন। https://hashnode.com/post/why-are-mongoose-mongodb-odm-lean-queries-faster-than-normal-queries-cillvawhq0062kj53asxoyn7j

সেভ ফাংশন নিয়ে আর একটি সমস্যা, এটি একই সাথে মাল্টি-সেভের সাথে বিরোধের ডেটা তৈরি করবে। Model.Update ধারাবাহিকভাবে ডেটা তৈরি করবে। সুতরাং নথির অ্যারেতে বহু আইটেম আপডেট করতে। আপনার পরিচিত প্রোগ্রামিং ভাষাটি ব্যবহার করুন এবং এর মতো কিছু চেষ্টা করুন, আমি এতে মঙ্গুজ ব্যবহার করি:

User.findOne({'_id': '4d2d8deff4e6c1d71fc29a07'}).lean().exec()
  .then(usr =>{
    if(!usr)  return
    usr.events.forEach( e => {
      if(e && e.profile==10 ) e.handled = 0
    })
    User.findOneAndUpdate(
      {'_id': '4d2d8deff4e6c1d71fc29a07'},
      {$set: {events: usr.events}},
      {new: true}
    ).lean().exec().then(updatedUsr => console.log(updatedUsr))
})

0

$ [] অপারেটর সমস্ত নেস্টেড অ্যারে নির্বাচন করে .. আপনি '$ []' দিয়ে সমস্ত অ্যারে আইটেম আপডেট করতে পারেন

.update({"events.profile":10},{$set:{"events.$[].handled":0}},false,true)

উল্লেখ


আপনি এখানে দয়া করে কেন "মিথ্যা, সত্য" অন্তর্ভুক্ত করবেন তা ব্যাখ্যা করতে পারেন? ডকুমেন্টেশনে এটি খুঁজে পাচ্ছি না।
গারসন

সমস্ত অবস্থানের অপারেটরকে ভুল উত্তর $[] দিন সুনির্দিষ্ট অ্যারেতে সমস্ত ক্ষেত্র আপডেট করে। কী কাজ করে তা ফিল্টারড পজিশনাল অপারেটর $[identifier]যা অ্যারে ক্ষেত্রগুলিতে অপারেটরগুলি নির্দিষ্ট শর্তগুলির সাথে মেলে। arrayFilters রেফারেন্সের সাথে ব্যবহার করা উচিত: ডকস.মোংডব.কম / ম্যানুয়াল / রিলেজ- নোটস / .6..6 / ২৯
লরেন্স ইগলস

0

দয়া করে সচেতন হন যে এই থ্রেডের কয়েকটি উত্তর ব্যবহারের পরামর্শ দিচ্ছে - [[] যা ভুল।

db.collection.update(
   {"events.profile":10},
   {$set:{"events.$[].handled":0}},
   {multi:true}
)

উপরের কোডটি "ইভেন্ট" অ্যারেতে সমস্ত উপাদানগুলির জন্য "পরিচালিত" 0-তে আপডেট করবে, তার "প্রোফাইল" মান নির্বিশেষে। ক্যোয়ারী {"events.profile":10}কেবলমাত্র পুরো দস্তাবেজ ফিল্টার করার জন্য, অ্যারেতে থাকা দস্তাবেজগুলি নয়। এ অবস্থায় এটি ব্যবহার করতে একটি আবশ্যক $[elem]সঙ্গে arrayFiltersতাই নিল Lunn এর উত্তরটি সঠিক অ্যারে আইটেম অবস্থার উল্লেখ করতে।


0

মোঙ্গো ডিবিতে একাধিক নথিতে অ্যারে ক্ষেত্রটি আপডেট করুন।

মঙ্গোডিবিতে অ্যারে উপাদানগুলি আপডেট করতে অনেক ক্যোয়ারী আপডেট সহ $ টান বা $ ধাক্কা ব্যবহার করুন।

Notification.updateMany(
    { "_id": { $in: req.body.notificationIds } },
    {
        $pull: { "receiversId": req.body.userId }
    }, function (err) {
        if (err) {
            res.status(500).json({ "msg": err });
        } else {
            res.status(200).json({
                "msg": "Notification Deleted Successfully."
            });
        }
    });

0

প্রথম: আপনার কোডটি কার্যকর হয়নি কারণ আপনি পজিশনাল অপারেটর ব্যবহার করছেন $যা কেবল অ্যারেতে আপডেট করার জন্য একটি উপাদান সনাক্ত করে তবে অ্যারেতে তার অবস্থানটি স্পষ্টভাবে নির্দিষ্ট করে না।

আপনার যা প্রয়োজন তা হ'ল ফিল্টারড পজিশনাল অপারেটর $[<identifier>]। এটি অ্যারে ফিল্টার শর্তের সাথে মেলে এমন সমস্ত উপাদান আপডেট করবে।

সমাধান:

db.collection.update({"events.profile":10}, { $set: { "events.$[elem].handled" : 0 } },
   {
     multi: true,
     arrayFilters: [ { "elem.profile": 10 } ]
})

মঙ্গডব ডক এখানে যান

কোডটি কী করে:

  1. {"events.profile":10} আপনার সংগ্রহটি ফিল্টার করে এবং ফিল্টারটির সাথে মিলে থাকা দস্তাবেজগুলি ফিরিয়ে দেয়

  2. $setআপডেটের অপারেটর: নথি ক্ষেত্র মিলে মডিফাই এটা কাজ করে।

  3. {multi:true}এটি .update()ফিল্টারটির সাথে মিলে এমন সমস্ত দস্তাবেজগুলিকে পরিবর্তিত করে যার ফলে আচরণ করা হয়updateMany()

  4. { "events.$[elem].handled" : 0 } and arrayFilters: [ { "elem.profile": 10 } ] এই কৌশলটিতে অ্যারেফিল্টারগুলি সহ ফিল্টারযুক্ত পজিশনাল অ্যারের ব্যবহার জড়িত। ফিল্টারযুক্ত অবস্থানগত অ্যারে এখানে অ্যারে ফিল্ডারে $[elem]উল্লিখিত অবস্থার সাথে মেলে এমন অ্যারে ক্ষেত্রগুলির সমস্ত উপাদানগুলির জন্য স্থানধারক হিসাবে কাজ করে।

অ্যারে ফিল্টার

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