删除“重复”是一个过程,并没有简单的方法来“识别”重复和“删除”他们作为一个单一的陈述。这里的另一个特殊之处是查询表单不能“典型地”确定数组的大小,并且当然不能在文档中不存在的情况下进行排序。
所有病例基本上回落到
标识是“重复”的文件列表,然后最好指法要删除特定文件,或者更重要的是该文件你“唐't'想从可能的重复项中删除。
处理该列表以实际执行删除。
考虑到这一点,你希望拥有的2.6或更高版本的现代化的MongoDB在那里你可以得到从aggregate方法的光标。你也想在这些版本中最佳速度可用Bulk Operations API:
var bulk = db.collection.initializeOrderedBulkOp();
var counter = 0;
db.collection.aggregate([
{ "$project": {
"id": 1,
"size": { "$size": "$someArray" }
}},
{ "$sort": { "id": 1, "size": -1 } },
{ "$group": {
"_id": "$id",
"docId": { "$first": "$_id" }
}}
]).forEach(function(doc) {
bulk.find({ "id": doc._id, "_id": { "$ne": doc.docId }).remove();
counter++;
// Send to server once every 1000 statements only
if (counter % 1000 == 0) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp(); // need to reset
}
});
// Clean up results that did not round to 1000
if (counter % 1000 != 0)
bulk.execute();
你仍然可以做同样的事情与旧版本的MongoDB,但是从.aggregate()
其结果必然是在16MB这是BSON限制。这仍然应该是很多,但使用旧版本,您也可以使用mapReduce输出到集合。
但是对于一般聚合响应,您会得到一组结果,并且您也没有其他便捷方法来查找数组的大小。所以多做点工作:
var result = db.collection.aggregate([
{ "$unwind": "$someArray" },
{ "$group": {
"_id": "$id",
"id": { "$first": "$id" },
"size": { "$sum": 1 }
}},
{ "$sort": { "id": 1, "size": -1 } },
{ "$group": {
"_id": "$id",
"docId": { "$first": "$_id" }
}}
]);
result.result.forEach(function(doc) {
db.collection.remove({ "id": doc._id, "_id": { "$ne": doc.docId } });
});
因此,没有游标较大的结果,没有批量操作使每一个“删除”需要单独发送到服务器。
所以在MongoDB中没有“子查询”,或者即使有超过“两个副本”的方式来选出您不希望从其他副本中删除的文档。但这是通用的方式。就像一个说明,如果数组的“大小”对于诸如“排序”等目的而言是重要的,那么最好的方法就是将“大小”作为文档的另一个属性,以便它使得这些操作更容易,无需像这里所做的那样“计算”。