use*_*659 50 optimization key duplicates mongodb
我在MongoDB中有一个集合,其中有大约(约300万条记录).我的样本记录看起来像,
{ "_id" = ObjectId("50731xxxxxxxxxxxxxxxxxxxx"),
"source_references" : [
"_id" : ObjectId("5045xxxxxxxxxxxxxx"),
"name" : "xxx",
"key" : 123
]
}
Run Code Online (Sandbox Code Playgroud)
我在集合中有很多重复记录source_references.key
.(重复我的意思是,source_references.key
不是_id
).
我想删除基于的重复记录source_references.key
,我正在考虑编写一些PHP代码来遍历每个记录并删除记录(如果存在).
有没有办法删除Mongo Internal命令行中的重复项?
Ste*_*nie 76
如果您source_references.key
确定标识重复记录,则可以使用dropDups:true
MongoDB 2.6或更早版本中的索引创建选项确保唯一索引:
db.things.ensureIndex({'source_references.key' : 1}, {unique : true, dropDups : true})
Run Code Online (Sandbox Code Playgroud)
这将保留每个source_references.key
值的第一个唯一文档,并删除任何可能导致重复键冲突的后续文档.
重要说明:
dropDups
选项已在MongoDB 3.0中删除,因此需要采用不同的方法.例如,您可以按照以下建议使用聚合:即使在添加唯一键后,MongoDB也会复制文档.source_references.key
字段的任何文档都将被视为具有空值,因此缺少关键字段的后续文档将被删除.您可以添加sparse:true
索引创建选项,以便索引仅适用于具有source_references.key
字段的文档.显而易见的警告:备份数据库,如果您担心意外的数据丢失,请先在暂存环境中尝试此操作.
Kan*_*hal 52
这是我在MongoDB 3.2上使用的最简单的查询
db.myCollection.find({}, {myCustomKey:1}).sort({_id:1}).forEach(function(doc){
db.myCollection.remove({_id:{$gt:doc._id}, myCustomKey:doc.myCustomKey});
})
Run Code Online (Sandbox Code Playgroud)
customKey
在运行此程序之前为您的索引以提高速度
虽然@ Stennie是一个有效的答案,但这不是唯一的方法.事实上,MongoDB手册要求您在执行此操作时要非常谨慎.还有两个选择
小智 8
这是一种稍微“手动”的方法:
本质上,首先,获取您感兴趣的所有唯一键的列表。
然后使用这些键中的每一个执行搜索,如果该搜索返回大于 1,则删除。
db.collection.distinct("key").forEach((num)=>{
var i = 0;
db.collection.find({key: num}).forEach((doc)=>{
if (i) db.collection.remove({key: num}, { justOne: true })
i++
})
});
Run Code Online (Sandbox Code Playgroud)
我有类似的要求,但我想保留最新的条目。以下查询适用于我的收藏,其中有数百万条记录和重复项。
/** Create a array to store all duplicate records ids*/
var duplicates = [];
/** Start Aggregation pipeline*/
db.collection.aggregate([
{
$match: { /** Add any filter here. Add index for filter keys*/
filterKey: {
$exists: false
}
}
},
{
$sort: { /** Sort it in such a way that you want to retain first element*/
createdAt: -1
}
},
{
$group: {
_id: {
key1: "$key1", key2:"$key2" /** These are the keys which define the duplicate. Here document with same value for key1 and key2 will be considered duplicate*/
},
dups: {
$push: {
_id: "$_id"
}
},
count: {
$sum: 1
}
}
},
{
$match: {
count: {
"$gt": 1
}
}
}
],
{
allowDiskUse: true
}).forEach(function(doc){
doc.dups.shift();
doc.dups.forEach(function(dupId){
duplicates.push(dupId._id);
})
})
/** Delete the duplicates*/
var i,j,temparray,chunk = 100000;
for (i=0,j=duplicates.length; i<j; i+=chunk) {
temparray = duplicates.slice(i,i+chunk);
db.collection.bulkWrite([{deleteMany:{"filter":{"_id":{"$in":temparray}}}}])
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
69766 次 |
最近记录: |