ewo*_*com 34 optimization performance duplicates mongodb
我在mongodb中有大约170万份文件(将来10m +).其中一些代表我不想要的重复条目.文档的结构是这样的:
{
_id: 14124412,
nodes: [
12345,
54321
],
name: "Some beauty"
}
Run Code Online (Sandbox Code Playgroud)
如果文档至少有一个节点与具有相同名称的另一个文档相同,则文档是重复的.删除重复项的最快方法是什么?
Som*_*luk 65
dropDups: true 选项在3.0中不可用.
我有聚合框架的解决方案,用于收集重复项,然后一次性删除.
它可能比系统级"索引"更改慢一些.但考虑到你想删除重复文件的方式很好.
一个.一次性删除所有文档
var duplicates = [];
db.collectionName.aggregate([
{ $match: {
name: { "$ne": '' } // discard selection criteria
}},
{ $group: {
_id: { name: "$name"}, // can be grouped on multiple properties
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $match: {
count: { "$gt": 1 } // Duplicates considered as count greater than one
}}
],
{allowDiskUse: true} // For faster processing if set is larger
) // You can display result until this and check duplicates
.forEach(function(doc) {
doc.dups.shift(); // First element skipped for deleting
doc.dups.forEach( function(dupId){
duplicates.push(dupId); // Getting all duplicate ids
}
)
})
// If you want to Check all "_id" which you are deleting else print statement not needed
printjson(duplicates);
// Remove all duplicates in one go
db.collectionName.remove({_id:{$in:duplicates}})
Run Code Online (Sandbox Code Playgroud)
湾 您可以逐个删除文档.
db.collectionName.aggregate([
// discard selection criteria, You can remove "$match" section if you want
{ $match: {
source_references.key: { "$ne": '' }
}},
{ $group: {
_id: { source_references.key: "$source_references.key"}, // can be grouped on multiple properties
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $match: {
count: { "$gt": 1 } // Duplicates considered as count greater than one
}}
],
{allowDiskUse: true} // For faster processing if set is larger
) // You can display result until this and check duplicates
.forEach(function(doc) {
doc.dups.shift(); // First element skipped for deleting
db.collectionName.remove({_id : {$in: doc.dups }}); // Delete remaining duplicates
})
Run Code Online (Sandbox Code Playgroud)
Joh*_*yHK 43
假设您要永久删除包含集合中的重复name+ nodes条目的文档,您可以unique使用以下dropDups: true选项添加索引:
db.test.ensureIndex({name: 1, nodes: 1}, {unique: true, dropDups: true})
Run Code Online (Sandbox Code Playgroud)
正如文档所说,使用它会非常谨慎,因为它会从数据库中删除数据.首先备份数据库,以防它没有按照您的预期完成.
UPDATE
此解决方案仅在MongoDB 2.x中有效,因为该dropDups选项在3.0(docs)中不再可用.
小智 14
以下 Mongo 聚合管道执行重复数据删除并将其输出回相同或不同的集合。
collection.aggregate([
{ $group: {
_id: '$field_to_dedup',
doc: { $first: '$$ROOT' }
} },
{ $replaceRoot: {
newRoot: '$doc'
} },
{ $out: 'collection' }
], { allowDiskUse: true })Run Code Online (Sandbox Code Playgroud)
我发现这个解决方案适用于MongoDB 3.4:我假设带有重复项的字段称为fieldX
db.collection.aggregate([
{
// only match documents that have this field
// you can omit this stage if you don't have missing fieldX
$match: {"fieldX": {$nin:[null]}}
},
{
$group: { "_id": "$fieldX", "doc" : {"$first": "$$ROOT"}}
},
{
$replaceRoot: { "newRoot": "$doc"}
}
],
{allowDiskUse:true})
Run Code Online (Sandbox Code Playgroud)
作为mongoDB的新手,我花了很多时间并使用其他冗长的解决方案来查找和删除重复项.但是,我认为这个解决方案简洁易懂.
它的工作原理是首先匹配包含fieldX的文档(我有一些没有这个字段的文档,我有一个额外的空结果).
下一阶段按字段X对文档进行分组,并且仅使用$$ ROOT在每个组中插入$ first文档.最后,它使用$ first和$$ ROOT找到的文档替换整个聚合组.
我不得不添加allowDiskUse,因为我的集合很大.
您可以在任意数量的管道之后添加它,虽然$ first的文档在使用$ first之前提到了一个排序阶段,但它没有它对我有用."不能在这里发布链接,我的声誉不到10 :("
您可以通过添加$ out阶段将结果保存到新集合中......
或者,如果一个人只对几个字段感兴趣,例如field1,field2,而不是整个文档,则在没有replaceRoot的组阶段:
db.collection.aggregate([
{
// only match documents that have this field
$match: {"fieldX": {$nin:[null]}}
},
{
$group: { "_id": "$fieldX", "field1": {"$first": "$$ROOT.field1"}, "field2": { "$first": "$field2" }}
}
],
{allowDiskUse:true})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
48620 次 |
| 最近记录: |