nếu bạn chuẩn bị sẵn sàng để loại bỏ tất cả các bản sao khác thì về cơ bản bạn muốn .aggregate()
để thu thập các tài liệu có cùng RegisterNumber
giá trị và loại bỏ tất cả các tài liệu khác với kết quả phù hợp đầu tiên.
MongoDB 3.0.x thiếu một số trình trợ giúp hiện đại nhưng những kiến thức cơ bản .aggregate()
trả về con trỏ cho các tập kết quả lớn của quá trình và sự hiện diện của "hoạt động hàng loạt"
đối với hiệu suất ghi vẫn tồn tại:
var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;
db.collection.aggregate([
// Group on unique value storing _id values to array and count
{ "$group": {
"_id": "$RegisterNumber",
"ids": { "$push": "$_id" },
"count": { "$sum": 1 }
}},
// Only return things that matched more than once. i.e a duplicate
{ "$match": { "count": { "$gt": 1 } } }
]).forEach(function(doc) {
var keep = doc.ids.shift(); // takes the first _id from the array
bulk.find({ "_id": { "$in": doc.ids }}).remove(); // remove all remaining _id matches
count++;
if ( count % 500 == 0 ) { // only actually write per 500 operations
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp(); // re-init after execute
}
});
// Clear any queued operations
if ( count % 500 != 0 )
bulk.execute();
Trong các bản phát hành hiện đại hơn (3.2 trở lên), ưu tiên sử dụng bulkWrite()
thay vì. Lưu ý rằng đây là một thứ thuộc về 'thư viện khách hàng', vì các phương thức "hàng loạt" tương tự được hiển thị ở trên thực sự được gọi là "ẩn":
var ops = [];
db.collection.aggregate([
{ "$group": {
"_id": "$RegisterNumber",
"ids": { "$push": "$id" },
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } }
]).forEach( doc => {
var keep = doc.ids.shift();
ops = [
...ops,
{
"deleteMany": { "filter": { "_id": { "$in": doc.ids } } }
}
];
if (ops.length >= 500) {
db.collection.bulkWrite(ops);
ops = [];
}
});
if (ops.length > 0)
db.collection.bulkWrite(ops);
Vì vậy, $group
kéo mọi thứ lại với nhau thông qua $RegisterNumber
giá trị và thu thập tài liệu phù hợp _id
giá trị của một mảng. Bạn đếm số lần điều này xảy ra bằng cách sử dụng $sum
.
Sau đó, lọc ra bất kỳ tài liệu nào chỉ có số lượng 1
vì chúng rõ ràng không phải là bản sao.
Chuyển đến vòng lặp, bạn xóa lần xuất hiện đầu tiên của _id
trong danh sách đã thu thập cho khóa có .shift()
, chỉ để lại các "bản sao" khác trong mảng.
Chúng được chuyển đến thao tác "remove" với $in
dưới dạng "danh sách" các tài liệu cần đối sánh và loại bỏ.
Quá trình này nói chung là giống nhau nếu bạn cần thứ gì đó phức tạp hơn, chẳng hạn như hợp nhất các chi tiết từ các tài liệu trùng lặp khác, chỉ là bạn có thể cần cẩn thận hơn nếu thực hiện điều gì đó như chuyển đổi trường hợp của "khóa duy nhất" và do đó thực sự xóa các bản sao trước trước khi viết các thay đổi đối với tài liệu cần sửa đổi.
Ở bất kỳ mức độ nào, việc tổng hợp sẽ làm nổi bật các tài liệu thực sự là "bản sao". Logic xử lý còn lại dựa trên bất kỳ điều gì bạn thực sự muốn làm với thông tin đó sau khi bạn xác định được chúng.