Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MongoDB

Tìm giá trị trùng lặp (duplicate) của một field trong MongoDB với Aggregation

Sử dụng Aggregation Pipeline ($group + $match) để tìm các giá trị field xuất hiện nhiều hơn 1 lần.

Pipeline chuẩn

db.collection.aggregate([
    { $group: { _id: "$tênTrường", count: { $sum: 1 } } },
    { $match: { count: { $gt: 1 } } },
    { $sort: { count: -1 } }  // Tùy chọn: sắp xếp theo số lượng giảm dần
]);

Ví dụ minh họa

Tạo collection findAllNonDistinctDemo với nhiều UserName trùng:

> db.findAllNonDistinctDemo.insertOne({ "UserName": "John", "UserAge": 28 });
> db.findAllNonDistinctDemo.insertOne({ "UserName": "Larry", "UserAge": 21 });
> db.findAllNonDistinctDemo.insertOne({ "UserName": "Larry", "UserAge": 23 });
> db.findAllNonDistinctDemo.insertOne({ "UserName": "David", "UserAge": 22 });
> db.findAllNonDistinctDemo.insertOne({ "UserName": "John", "UserAge": 26 });
> db.findAllNonDistinctDemo.insertOne({ "UserName": "Robert", "UserAge": 24 });
> db.findAllNonDistinctDemo.insertOne({ "UserName": "Robert", "UserAge": 25 });
> db.findAllNonDistinctDemo.insertOne({ "UserName": "Mike", "UserAge": 29 });

Hiển thị tất cả:

> db.findAllNonDistinctDemo.find().pretty();

Tìm UserName trùng lặp

> db.findAllNonDistinctDemo.aggregate([
    { $group: { _id: "$UserName", Counter: { $sum: 1 } } },
    { $match: { Counter: { $gt: 1 } } }
]).pretty();

Kết quả:

{ "_id" : "Robert", "Counter" : 2 }
{ "_id" : "Larry", "Counter" : 2 }
{ "_id" : "John", "Counter" : 2 }

Mở rộng: Lấy cả _id của các document trùng

db.findAllNonDistinctDemo.aggregate([
    { $group: { _id: "$UserName", ids: { $push: "$_id" }, count: { $sum: 1 } } },
    { $match: { count: { $gt: 1 } } },
    { $project: { _id: 0, UserName: "$_id", count: 1, ids: 1 } }
]);

Kết quả:

{ "UserName" : "Robert", "count" : 2, "ids" : [ ObjectId("..."), ObjectId("...") ] }
{ "UserName" : "Larry", "count" : 2, "ids" : [ ObjectId("..."), ObjectId("...") ] }
{ "UserName" : "John", "count" : 2, "ids" : [ ObjectId("..."), ObjectId("...") ] }

Xử lý trùng lặp (Deduplication)

Giữ 1 document (thường là _id nhỏ nhất/đầu tiên), xóa các bản còn lại:

db.findAllNonDistinctDemo.aggregate([
    { $sort: { _id: 1 } },
    { $group: { _id: "$UserName", docId: { $first: "$_id" }, dupIds: { $push: "$_id" } } },
    { $match: { $expr: { $gt: [{ $size: "$dupIds" }, 1] } } },
    { $project: { _id: 0, idsToDelete: { $slice: ["$dupIds", 1, { $size: "$dupIds" }] } } }
]).forEach(doc => {
    db.findAllNonDistinctDemo.deleteMany({ _id: { $in: doc.idsToDelete } });
});

Phòng ngừa: Unique Index

db.collection.createIndex({ "UserName": 1 }, { unique: true });

Tạo index này sẽ **chặn insert/update** tạo ra duplicate. Nếu dữ liệu đã có duplicate, phải dọn dẹp trước khi tạo index.