การลบเอกสารซ้ำที่มีค่า field เดียวกัน 2 fields (Composite Key) ทำได้ด้วย aggregate pipeline ใช้ $group จัดกลุ่ม $first เก็บเอกสารแรก แล้ว $out เขียนทับคอลเลกชันเดิม
สร้างคอลเลกชันและข้อมูลตัวอย่าง (มีข้อมูลซ้ำ)
> db.demo108.insertOne({"Value1":23,"Value2":24});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2ee3e49fd5fd66da214477") }
> db.demo108.insertOne({"Value1":23,"Value2":25});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2ee3f29fd5fd66da214478") }
> db.demo108.insertOne({"Value1":23,"Value2":24}); // ซ้ำกับตัวแรก
{ "acknowledged" : true, "insertedId" : ObjectId("5e2ee3f59fd5fd66da214479") }
แสดงข้อมูลก่อนลบซ้ำ
> db.demo108.find();
ผลลัพธ์ (3 เอกสาร มีคู่ Value1=23, Value2=4 ซ้ำ 2 รายการ):
{ "_id" : ObjectId("5e2ee3e49fd5fd66da214477"), "Value1" : 23, "Value2" : 24 }
{ "_id" : ObjectId("5e2ee3f29fd5fd66da214478"), "Value1" : 23, "Value2" : 25 }
{ "_id" : ObjectId("5e2ee3f59fd5fd66da214479"), "Value1" : 23, "Value2" : 24 }
Query ลบข้อมูลซ้ำด้วย Aggregate + $out
> db.demo108.aggregate([
{ "$sort": { "_id": 1 } },
{
"$group": {
"_id": { "Value1": "$Value1", "Value2": "$Value2" },
"doc": { "$first": "$$ROOT" }
}
},
{ "$replaceRoot": { "newRoot": "$doc" } },
{ "$out": "demo108" }
]);
คำอธิบายขั้นตอน:
$sort: {_id: 1}: เรียงตาม _id เก่าไปใหม่ (เก็บตัวแรกที่ insert)$group: จัดกลุ่มตาม composite key (Value1, Value2) เก็บเอกสารแรก ($first) ของแต่ละกลุ่ม$replaceRoot: นำ doc ที่เก็บไว้ มาเป็น root document ใหม่$out: "demo108": เขียนผลลัพธ์ทับคอลเลกชันเดิม (แทนที่ข้อมูลทั้งหมด)
ผลลัพธ์หลังลบซ้ำ
> db.demo108.find();
ผลลัพธ์ (เหลือ 2 เอกสาร ไม่ซ้ำ):
{ "_id" : ObjectId("5e2ee3f29fd5fd66da214478"), "Value1" : 23, "Value2" : 25 }
{ "_id" : ObjectId("5e2ee3e49fd5fd66da214477"), "Value1" : 23, "Value2" : 24 }
วิธีอื่น: สร้าง Unique Index (ป้องกันล่วงหน้า)
db.demo108.createIndex({Value1: 1, Value2: 1}, {unique: true})
จะป้องกันการ insert ซ้ำในอนาคต แต่ต้องลบข้อมูลซ้ำเดิมก่อนสร้าง index
ลบซ้ำโดยเก็บ _id ใหม่ (ไม่เก็บ _id เดิม)
db.demo108.aggregate([
{ $group: { _id: {Value1: "$Value1", Value2: "$Value2"}, doc: { $first: "$$ROOT" }}},
{ $replaceRoot: { newRoot: "$doc" }},
{ $project: { _id: 0 }}, // ลบ _id เดิม
{ $out: "demo108" }
])
ข้อควรระวัง: $out จะลบคอลเลกชันเดิมและสร้างใหม่ - index ทั้งหมดจะหายไป ต้องสร้าง index ใหม่หลังรัน