Tìm bản ghi trùng lặp trong MongoDB


116

Làm cách nào để tìm các trường trùng lặp trong bộ sưu tập mongo.

Tôi muốn kiểm tra xem có bất kỳ trường "tên" nào trùng lặp không.

{
    "name" : "ksqn291",
    "__v" : 0,
    "_id" : ObjectId("540f346c3e7fc1054ffa7086"),
    "channel" : "Sales"
}

Cảm ơn nhiều!


5
Cờ trùng lặp cho câu hỏi này không được cung cấp. Câu hỏi này hỏi làm thế nào để tìm các bản ghi trùng lặp, không phải để ngăn chặn chúng.
Harry King

Câu trả lời:


209

Sử dụng tổng hợp trên namevà nhận namevới count > 1:

db.collection.aggregate(
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)

Để sắp xếp kết quả theo nhiều nhất đến ít trùng lặp nhất:

db.collection.aggregate(
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$sort": {"count" : -1} },
    {"$project": {"name" : "$_id", "_id" : 0} }     
)

Để sử dụng với tên cột khác không phải "name", hãy đổi " $ name " thành " $ column_name "


1
"$match": {"_id" :{ "$ne" : null } - là không cần thiết ở đây, vì phần thứ hai của câu lệnh sẽ đủ lọc kết quả. Vì vậy, chỉ kiểm tra nhóm có count > 1sẽ làm.
BatScream

5
Tks @BatScream. {"$ ne": null} chỉ có trong trường hợp 'name' là rỗng hoặc không tồn tại. Tổng hợp cũng sẽ tính là null.
anhlc

1
Chào mừng. Nhưng tại sao lại kiểm tra _idlĩnh vực này. Nó luôn được đảm bảo không bị vô hiệu sau khi grouphoạt động.
BatScream

4
Các _idcủa một tài liệu từ một $groupgiai đoạn có thể được null.
wdberkeley

1
Đầu ra của điều này sẽ là gì? Nếu tôi chạy, tôi nhận được tất cả các tài liệu mà tôi cần là tôi chỉ muốn tên / id trùng lặp.
Kannan T

24

Bạn có thể tìm ra listcác duplicatetên bằng cách sử dụng sau đây aggregateđường ống:

  • Grouptất cả các bản ghi có tương tự name.
  • Matchnhững người groupscó hồ sơ lớn hơn 1.
  • Sau đó, groupmột lần nữa cho projecttất cả các tên trùng lặp dưới dạng một array.

Mật mã:

db.collection.aggregate([
{$group:{"_id":"$name","name":{$first:"$name"},"count":{$sum:1}}},
{$match:{"count":{$gt:1}}},
{$project:{"name":1,"_id":0}},
{$group:{"_id":null,"duplicateNames":{$push:"$name"}}},
{$project:{"_id":0,"duplicateNames":1}}
])

o / p:

{ "duplicateNames" : [ "ksqn291", "ksqn29123213Test" ] }

10

Câu trả lời mà anhic đưa ra có thể rất kém hiệu quả nếu bạn có một cơ sở dữ liệu lớn và tên thuộc tính chỉ có trong một số tài liệu.

Để nâng cao hiệu quả, bạn có thể thêm $ match vào tổng hợp.

db.collection.aggregate(
    {"$match": {"name" :{ "$ne" : null } } }, 
    {"$group" : {"_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)

3
db.getCollection('orders').aggregate([  
    {$group: { 
            _id: {name: "$name"},
            uniqueIds: {$addToSet: "$_id"},
            count: {$sum: 1}
        } 
    },
    {$match: { 
        count: {"$gt": 1}
        }
    }
])

Nhóm đầu tiên Truy vấn nhóm theo các trường.

Sau đó, chúng tôi kiểm tra Id duy nhất và đếm nó, Nếu số lượng lớn hơn 1 thì trường đó là trùng lặp trong toàn bộ tập hợp để thứ đó sẽ được xử lý bởi truy vấn $ match.


1
tôi cũng không thể làm cho cái này hoạt động được. Bỏ phiếu xuống!
Mathieu G

Bài đăng này đã cũ nhưng có thể giúp ích cho một số người. kiểm tra điều này Tôi sẽ kiểm tra tại địa phương của tôi nó đang hoạt động. Ngay cả khi tôi đã xem qua một blog về điều này. Mời các bạn xem qua. compose.com/articles/finding-duplicate-documents-in-mongodb
Aman Shrivastava

Tôi đã có thể làm cho nó hoạt động - đã chỉnh sửa để cập nhật lên phiên bản làm việc được xác nhận.
AL Strine
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.