例如,我的收藏中有以下文件:
{
"_id" : "GuqXmAkkARqhBDqhy",
"beatmapset_id" : "342537",
"version" : "MX",
"diff_approach" : "5",
"artist" : "Yousei Teikoku",
"title" : "Kokou no Sousei",
"difficultyrating" : "3.5552737712860107"
}
{
"_id" : "oHLT7KqsB7bztBGvu",
"beatmapset_id" : "342537",
"version" : "HD",
"diff_approach" : "5",
"artist" : "Yousei Teikoku",
"title" : "Kokou no Sousei",
"difficultyrating" : "2.7515676021575928"
}
{
"_id" : "GbotZfrPEwW69FkGD",
"beatmapset_id" : "342537",
"version" : "NM",
"diff_approach" : "5",
"artist" : "Yousei Teikoku",
"title" : "Kokou no Sousei",
"difficultyrating" : "0"
}
这些文件具有相同的密钥beatmapset_id
我想删除所有重复项,但保留最多difficultyrating
的文档。
我尝试了db.collection.ensureIndex({beatmapset_id: 1}, {unique: true, dropDups: true})
,但它留下了一份随机文档,我想要上述条件。
我该怎么做?
答案 0 :(得分:2)
首先,您需要更新文档并将difficultyrating
和beatmapset_id
更改为浮点数。为此,您需要使用.forEach
方法遍历每个文档,并使用"Bulk"操作更新每个文档,以实现最高效率。
var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;
db.collection.find().forEach(function(doc) {
bulk.find({ '_id': doc._id }).update({
'$set': {
'beatmapset_id': parseFloat(doc.beatmapset_id),
'difficultyrating': parseFloat(doc.difficultyrating)
}
});
count++;
if(count % 100 == 0) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
})
if(count > 0) {
bulk.execute();
}
现在和#34; dropDups"索引创建的语法已被弃用"从MongoDB 2.6开始,在MongoDB 3.0中删除。这是你删除重复的方法。
这里的主要思想是首先按difficultyrating
按降序对文档进行排序。
bulk = db.collection.initializeUnorderedBulkOp();
count = 0;
db.collection.aggregate([
{ '$sort': { 'difficultyrating': -1 }},
{ '$group': { '_id': '$beatmapset_id', 'ids': { '$push': '$_id' }, 'count': { '$sum': 1 }}},
{ '$match': { 'count': { '$gt': 1 }}}
]).forEach(function(doc) {
doc.ids.shift();
bulk.find({'_id': { '$in': doc.ids }}).remove();
count++;
if(count === 100) {
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
})
if(count !== 0) {
bulk.execute();
}
此answer涵盖了主题以获取更多详细信息。
答案 1 :(得分:1)
您可以采取的一种方法是通过聚合框架获取具有重复 beatmapset_id
的文档的唯一ID列表:
db.collection.aggregate([
{
"$group": {
"_id": "$beatmapset_id",
"count": { "$sum": 1 },
"uniqueIds": { "$addToSet": "$_id" },
"maxRating": { "$max": "$difficultyrating" }
}
},
{
"$match": {
"count": { "$gte": 2 }
}
},
{
"$sort" : { "count" : -1 }
}
]);
在此示例管道的第一阶段,我们使用 $group
运算符按所需的索引键值聚合文档,并记录(在uniqueIds字段中)每个{{1}分组文档的值。我们还使用 $sum
运算符计算分组文档的数量,该运算符将传递给它的字段的值相加,在本例中为常量1 - 从而计算分组记录的数量进入计数领域。我们还使用 $max
运算符获得该组的最大_id
值。
在此示例管道的第二阶段,我们使用 $match
运算符过滤掉所有计数为1的文档。过滤掉的文档代表唯一索引键。< / p>
其余文档标识集合中包含重复键的文档。
示例输出:
difficultyrating
由于 db.collection.aggregate()
方法返回游标并且可以返回任意大小的结果集,因此请使用 cursor 方法 {{ 3}} 迭代光标并访问结果文档,然后使用 forEach()
Bulk API 操作简化:
/* 0 */
{
"result" : [
{
"_id" : "342537",
"count" : 3,
"uniqueIds" : [
"GbotZfrPEwW69FkGD",
"oHLT7KqsB7bztBGvu",
"GuqXmAkkARqhBDqhy"
],
"maxRating" : "3.5552737712860107"
}
],
"ok" : 1
}