Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

MongoDB Query: อัปเดต Field โดยแก้ไขข้อมูลเดิมใน Column

การอัปเดต field โดยใช้ค่าเดิมของ field นั้นๆ ในการคำนวณค่าใหม่ (เช่นเพิ่ม prefix) ทำได้ด้วย find().forEach() loop ใน Mongo Shell หรือ $function ใน aggregate (MongoDB 4.4+)

สร้างคอลเลกชันและข้อมูลตัวอย่าง

> db.demo115.insertOne({"LastName":"Brown"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2efe9bd8f64a552dae635a") }

แสดงข้อมูลก่อนอัปเดต

> db.demo115.find();

ผลลัพธ์: { "_id" : ObjectId(...), "LastName" : "Brown" }

Query อัปเดตด้วย forEach Loop (Mongo Shell)

> db.demo115.find({"LastName":"Brown"}).forEach(function(d) {
...   db.demo115.update(
...     {_id: d._id},
...     {$set: {LastName: 'Hello ' + d.LastName}}
...   );
... })

คำอธิบาย:

  • find({"LastName":"Brown"}): หาเอกสารที่ LastName="Brown"
  • .forEach(function(d) {...}): วนลูปแต่ละเอกสาร (d = document)
  • d.LastName: เข้าถึงค่าเดิมของ field
  • $set: {LastName: 'Hello ' + d.LastName}: ตั้งค่าใหม่ = "Hello " + ค่าเดิม

ผลลัพธ์หลังอัปเดต

> db.demo115.find();

ผลลัพธ์:

{ "_id" : ObjectId("5e2efe9bd8f64a552dae635a"), "LastName" : "Hello Brown" }

วิธีใหม่: ใช้ $set กับ Aggregation Pipeline (MongoDB 4.2+)

อัปเดตแบบ atomic ใน single operation ไม่ต้อง loop:

db.demo115.updateMany(
  {"LastName": "Brown"},
  [
    { $set: { LastName: { $concat: ["Hello ", "$LastName"] } } }
  ]
)

ข้อดี:

  • Atomic (ไม่มี race condition)
  • เร็วกว่า (single round trip)
  • ทำงานบน server side

ใช้ $function สำหรับ Logic ซับซ้อน (MongoDB 4.4+)

db.demo115.updateMany(
  {"LastName": "Brown"},
  [
    { $set: {
      LastName: {
        $function: {
          body: function(lastName) { return "Hello " + lastName; },
          args: ["$LastName"],
          lang: "js"
        }
      }
    }}
  ]
)

ตัวอย่างอื่น: เพิ่ม Suffix, แปลง Case, คำนวณเลข

// เพิ่ม suffix
{$set: {Name: {$concat: ["$Name", " Jr."]}}}

// Uppercase
{$set: {Name: {$toUpper: "$Name"}}}

// คูณค่า
{$set: {Price: {$multiply: ["$Price", 1.1]}}}

สรุป: MongoDB 4.2+ ใช้ update with aggregation pipeline ($set + $concat) แทน forEach loop จะได้ atomic และเร็วกว่า