ค้นหาระเบียนที่ซ้ำกันใน MongoDB


118

ฉันจะค้นหาฟิลด์ที่ซ้ำกันในคอลเลกชัน Mongo ได้อย่างไร

ฉันต้องการตรวจสอบว่าช่อง "ชื่อ" ซ้ำกันหรือไม่

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

ขอบคุณมาก!


5
ค่าสถานะที่ซ้ำกันสำหรับคำถามนี้ไม่ถูกสงวนไว้ คำถามนี้ถามถึงวิธีค้นหาระเบียนที่ซ้ำกันไม่ใช่เพื่อป้องกัน
Harry King

คำตอบ:


213

ใช้การรวมnameและรับnameกับcount > 1:

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

วิธีจัดเรียงผลลัพธ์ตามรายการที่ซ้ำกันมากที่สุดไปหาน้อยที่สุด:

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

หากต้องการใช้กับชื่อคอลัมน์อื่นที่ไม่ใช่ "ชื่อ" ให้เปลี่ยน " $ name " เป็น " $ column_name "


1
"$match": {"_id" :{ "$ne" : null } - ไม่จำเป็นที่นี่เนื่องจากส่วนที่สองของคำสั่งจะเพียงพอในการกรองผลลัพธ์ ดังนั้นการตรวจสอบเฉพาะกลุ่มที่ต้องcount > 1ทำ
BatScream

5
Tks @BatScream. {"$ ne": null} ในกรณีที่ "name" เป็นโมฆะหรือไม่มีอยู่จริง การรวมจะนับเป็นโมฆะเช่นกัน
anhlc

1
ยินดีต้อนรับ. แต่แล้วทำไมต้องตรวจสอบ_idสนาม รับประกันได้เสมอว่าจะไม่เป็นโมฆะหลังการgroupดำเนินการ
BatScream

4
_idของเอกสารจากที่$groupเวทีสามารถเป็นโมฆะ
wdberkeley

1
ผลลัพธ์ของสิ่งนี้จะเป็นอย่างไร? ถ้าฉันเรียกใช้ฉันได้รับเอกสารทั้งหมดที่ฉันต้องการคือฉันต้องการเฉพาะ id / ชื่อที่ซ้ำกัน
คาน T

24

คุณสามารถค้นหาlistของduplicateชื่อใช้ต่อไปนี้aggregateท่อ:

  • Groupnameระเบียนทั้งหมดที่มีลักษณะคล้ายกัน
  • Matchผู้ที่มีบันทึกมากกว่าgroups1
  • จากนั้นgroupอีกครั้งสำหรับprojectชื่อที่ซ้ำกันทั้งหมดเป็นarrayไฟล์.

รหัส:

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

คำตอบที่ anhic ให้อาจไม่มีประสิทธิภาพมากหากคุณมีฐานข้อมูลขนาดใหญ่และมีชื่อแอตทริบิวต์อยู่ในเอกสารบางส่วนเท่านั้น

ในการปรับปรุงประสิทธิภาพคุณสามารถเพิ่มการจับคู่ $ ลงในการรวมได้

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}
        }
    }
])

กลุ่มแรกค้นหากลุ่มตามฟิลด์

จากนั้นเราตรวจสอบ Id ที่ไม่ซ้ำกันและนับถ้าจำนวนมากกว่า 1 แสดงว่าฟิลด์นั้นซ้ำกันในคอลเล็กชันทั้งหมดดังนั้นสิ่งนั้นจะถูกจัดการโดย $ match query


1
ยังไม่สามารถทำให้สิ่งนี้ใช้ได้กับฉันด้วย ลงคะแนน!
Mathieu G

โพสต์นี้เก่า แต่อาจช่วยได้บ้าง ตรวจสอบสิ่งนี้ฉันจะตรวจสอบในท้องถิ่นของฉันมันใช้งานได้ แม้แต่ฉันก็เจอบล็อกหนึ่งเกี่ยวกับเรื่องนี้ โปรดดู compose.com/articles/finding-duplicate-documents-in-mongodb
Aman shrivastava

ฉันสามารถทำให้มันใช้งานได้ - แก้ไขเพื่ออัปเดตเป็นเวอร์ชันที่ใช้งานได้ที่ยืนยันแล้ว
AL Strine
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.