فصل جدید؛ نگاهی عمیق‌تر به عملیات UPDATE در MongoDB

Take a Deeper Look at UPDATE Operations in MongoDB

20 اردیبهشت 1401
درسنامه درس 41 از سری دوره جامع آموزش MongoDB
MongoDB: فصل جدید، نگاهی عمیق تر به عملیات UPDATE (قسمت 43)

در فصل های قبل به طور خلاصه برخی از دستورات UPDATE را بررسی کردیم اما در این فصل می خواهیم به جزئیات ریز آن ها بپردازیم. بیایید با مرورگر بر دستورات updateOne و updateMany شروع کنیم. در این فصل با همان پایگاه داده user شروع می کنیم که چند اطلاعات زیر را در خود داشت:

        "_id" : ObjectId("5eb295a448ff1d422538a355"),
        "name" : "Amir",
        "hobbies" : [
                {
                        "title" : "programming",
                        "frequency" : 3
                },
                {
                        "title" : "Gym",
                        "frequency" : 6
                }
        ],
        "phone" : 59732894409174
}

        "_id" : ObjectId("5eb295a448ff1d422538a356"),
        "name" : "Nastaran",
        "hobbies" : [
                {
                        "title" : "Reading",
                        "frequency" : 5
                },
                {
                        "title" : "Movies",
                        "frequency" : 7
                }
        ],
        "phone" : "352380532895",
        "age" : 30
}

        "_id" : ObjectId("5eb299c448ff1d422538a357"),
        "name" : "Ahmad",
        "hobbies" : [
                {
                        "title" : "Counceling",
                        "frequency" : 100
                },
                {
                        "title" : "Farming",
                        "frequency" : 7
                }
        ],
        "phone" : "3131031385734943",
        "age" : null
}

        "_id" : ObjectId("5eb3c250c91228985d228864"),
        "name" : "Pooya",
        "hobbies" : [
                "Sports",
                "Cooking",
                "Hiking"
        ]
}

        "_id" : ObjectId("5eb3e69ac91228985d228865"),
        "name" : "Javad",
        "hobbies" : [
                {
                        "title" : "Gym",
                        "frequency" : 2
                },
                {
                        "title" : "Driving",
                        "frequency" : 4
                }
        ]
}

فرض کنید بخواهیم pooya را update کنیم. راه های مختلفی برای انجام این کار وجود دارد اما کلیت کار در دو مرحله انجام می شود: اول باید کاربر را شناسایی و پیدا کنیم، سپس باید بگوییم چه چیزی تغییر کند. برای شناسایی کاربر می توانید از هر چیزی استفاده کنید اما از آنجایی که استفاده از id معمولا روش شناخته شده تری است من از id استفاده می کنم. سوال بعدی اینجاست که از چه دستوری برای update کردن اطلاعات استفاده کنیم. ما دو دستور اصلی updateOne و updateMany را داریم که تفاوت آن ها بسیار ساده است: دستور updateOne اولین عنصری را که بر اساس شرط شما پیدا کند تغییر می دهد حتی اگر چندین عنصر با شرط ذکر شده پیدا شوند (همان مفهوم first match) اما updateMany تمام عناصری که با شرط شما پیدا شوند را ویرایش خواهد کرد. البته در هر جایی از برنامه که یک فیلد دارید نیز می توانید از updateMany استفاده کنید و اینطور نیست که حتما باید چند سند داشته باشید تا از آن استفاده نمایید. updateMany یعنی یک یا بیشتر ولی updateOne یعنی فقط یکی!

برای شروع می گوییم:

db.users.updateOne({_id: ObjectId("5eb3c250c91228985d228864")}, {})

آرگومان اولی که به updateOne داده ام همان شرط یا فیلتر ما برای پیدا کردن یک سند خاص است اما آرگومان دوم مشخص می کند که این سند چطور باید تغییر کند. در این آرگومان می توانیم از اپراتور های مختلف مربوط به update استفاده کنیم (در مورد آن ها صحبت خواهیم کرد). من می خواهم از اپراتوری که قبلا دیدیم، یعنی set$، استفاده کنم:

db.users.updateOne({_id: ObjectId("5eb3c250c91228985d228864")}, {$set: {hobbies: [{title: "Sports", frequency: 5}, {title: "Cooking", frequency: 3}, {title: "Hiking", frequency: 1}]}})

اپراتور $set باعث نمی شود که موارد ذکر شده به قسمت hobbies اضافه شوند بلکه کاملا جایگزین این قسمت می شوند. از آنجایی که کاربر Pooya در قسمت hobbies خود با بقیه تفاوت داشت (به جای داشتن اشیاء درون آرایه hobbies، مستقیما رشته ها را داشتیم) می خواستم آن را شبیه به بقیه کاربران کنم به همین دلیل کد بالا را نوشتم. با اجرای کد بالا پیام زیر را می گیرید:

{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

یعنی 1 سند بر اساس فیلتر ما پیدا شده است (matchedCount) که از آن 1 سند نیز ویرایش شده است (modifiedCount). حالا اگر کوئری خود را دوباره اجرا کنیم چه می شود؟ پیام زیر را می گیریم:

{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }

یعنی یک سند بر اساس فیلتر ما پیدا شده است اما صفر سند ویرایش شده اند. چرا؟ به دلیل اینکه کوئری ما دقیقا همان داده هایی را دارد که درون سند ذخیره شده است بنابراین نیازی به تغییر نیست. در ضمن توجه داشته باشید که Pooya هنوز نام خود و id_ خود را حفظ کرده است و فقط قسمت hobbies تغییر کرده است. برای ثابت کردن این مسئله می توانیم آن را بر اساس id اش جست و جو کنیم:

db.users.find(ObjectId("5eb3c250c91228985d228864")).pretty()

خروجی:

"_id" : ObjectId("5eb3c250c91228985d228864"), 
 "name" : "Pooya",                             
 "hobbies" : [                                 
         {                                     
                 "title" : "Sports",           
                 "frequency" : 5               
         },                                    
         {                                     
                 "title" : "Cooking",          
                 "frequency" : 3               
         },                                    
         {                                     
                 "title" : "Hiking",           
                 "frequency" : 1               
         }                                     
 ]                                             

اگر من بخواهم تمام افرادی را پیدا کنم که در hobbies خود Gym را دارند باید چه کار کنم؟ این مورد را در فصل قبل یاد گرفتیم و نحوه انجام آن را می دانیم:

db.users.find({"hobbies.title": "Gym"}).pretty()

با این کار دو کاربر Amir و Javad را می بینیم چرا که تنها کاربرانی هستند که Gym را در hobbies خود دارند. حالا اگر بخواهیم به هر دو این کاربران یک فیلد جدید اضافه کنیم، باید چه کار کنیم؟

db.users.updateMany({"hobbies.title": "Gym"}, {$set: {isSporty: true}})

ما برای انجام این کار از updateMany استفاده کرده ایم و خصوصیت جدید isSporty (اهل ورزش بودن) را برای آن ها روی true گذاشته ایم. با اجرای این دستور پیام زیر را دریافت می کنیم:

{ "acknowledged" : true, "matchedCount" : 2, "modifiedCount" : 2 }

یعنی 2 سند پیدا شده و هر دو سند ویرایش شده است. زمانی که set$ فیلد مورد نظر را پیدا نکند، آن را به طور خودکار ایجاد خواهد کرد بنابراین ویرایش کردن isSporty به true یعنی یک خصوصیت به نام isSporty بساز که مقدار آن True باشد. حالا اطلاعات Amir و Javad به شکل زیر است:

"_id" : ObjectId("5eb295a448ff1d422538a355"), 
 "name" : "Amir",                              
 "hobbies" : [                                 
         {                                     
                 "title" : "programming",      
                 "frequency" : 3               
         },                                    
         {                                     
                 "title" : "Gym",              
                 "frequency" : 6               
         }                                     
 ],                                            
 "phone" : 59732894409174,                     
 "isSporty" : true                             
                                               
                                               
 "_id" : ObjectId("5eb3e69ac91228985d228865"), 
 "name" : "Javad",                             
 "hobbies" : [                                 
         {                                     
                 "title" : "Gym",              
                 "frequency" : 2               
         },                                    
         {                                     
                 "title" : "Driving",          
                 "frequency" : 4               
         }                                     
 ],                                            
 "isSporty" : true                          

همانطور که می بینید خصوصیت isSporty برای هر دو کاربر ایجاد شده است. ما تا اینجا از set$ برای تغییر یک فیلد در هر سند استفاده کرده ایم اما می توانید از آن برای ویرایش چندین فیلد نیز استفاده نمایید. مثلا Pooya هنوز شماره تلفن و سن ندارد بنابراین می توانیم هر دوی این فیلد ها را با set$ به سند مربوطه اش اضافه کنیم:

db.users.updateOne({_id: ObjectId("5eb3c250c91228985d228864")}, {$set: {age: 25, phone: 75834965320948}})

همانطور که می بینید من هر دو فیلد age و phone را با هم ویرایش کرده ام (البته از آنجایی که Pooya این فیلد ها را نداشت، به صورت خودکار برایش ساخته خواهد شد). حالا می توانیم دستور زیر را اجرا کنیم:

db.users.find({_id: ObjectId("5eb3c250c91228985d228864")}).pretty()

با اجرای این دستور نتیجه زیر را می بینیم:

"_id" : ObjectId("5eb3c250c91228985d228864"),
 "name" : "Pooya",                            
 "hobbies" : [                                
         {                                    
                 "title" : "Sports",          
                 "frequency" : 5              
         },                                   
         {                                    
                 "title" : "Cooking",         
                 "frequency" : 3              
         },                                   
         {                                    
                 "title" : "Hiking",          
                 "frequency" : 1              
         }                                    
 ],                                           
 "age" : 25,                                  
 "phone" : 75834965320948                      
تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش MongoDB توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مقالات مرتبط
آخرین سوالات کاربران
5451218 در 4 سال قبل پرسیده:
ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو