我有一个查询,它选择要删除的文档。现在,我手动删除它们(使用python):
for id in mycoll.find(query, fields={}):
mycoll.remove(id)
这似乎不是很有效。还有更好的方法吗?
修改
好的,我遗憾地忘记提及查询详情,因为这很重要。这是完整的python代码:
def reduce_duplicates(mydb, max_group_size):
# 1. Count the group sizes
res = mydb.static.map_reduce(jstrMeasureGroupMap, jstrMeasureGroupReduce, 'filter_scratch', full_response = True)
# 2. For each entry from the filter scratch collection having count > max_group_size
deleteFindArgs = {'fields': {}, 'sort': [('test_date', ASCENDING)]}
for entry in mydb.filter_scratch.find({'value': {'$gt': max_group_size}}):
key = entry['_id']
group_size = int(entry['value'])
# 2b. query the original collection by the entry key, order it by test_date ascending, limit to the group size minus max_group_size.
for id in mydb.static.find(key, limit = group_size - max_group_size, **deleteFindArgs):
mydb.static.remove(id)
return res['counts']['input']
那么,它做了什么?它会将重复键的数量减少到每个键值最多max_group_size
,只保留最新记录。它的工作原理如下:
(key, count)
对。count > max_group_size
key
查询数据,同时按时间戳(最早的第一个)进行排序,并将结果限制为count - max_group_size
最早的记录正如您所看到的,这完成了将重复项减少到最多N个最新记录的任务。所以,最后两个步骤是foreach-found-remove
,这是我的问题的重要细节,它改变了一切,我必须更加具体 - 抱歉。
现在,关于集合删除命令。它接受查询,但我的包括排序和限制。我可以删除吗?好吧,我试过了:
mydb.static.find(key, limit = group_size - max_group_size, sort=[('test_date', ASCENDING)])
这种尝试失败了。而且,它似乎是mongo.Observe:
C:\dev\poc\SDR>python FilterOoklaData.py
bad offset:0 accessing file: /data/db/ookla.0 - consider repairing database
毋庸置疑,foreach-found-remove方法有效并产生预期结果。
现在,我希望我已经提供了足够的背景,并且(希望)已经恢复了我失去的荣誉。
答案 0 :(得分:34)
您可以使用查询删除所有匹配的文档
var query = {name: 'John'};
db.collection.remove(query);
但要小心,如果匹配文档的数量很多,您的数据库可能会降低响应速度。通常建议删除较小块的文档。
假设您有100k个要从集合中删除的文档。最好执行100个删除1k文档的查询,而不是删除所有100k文档的1个查询。
答案 1 :(得分:10)
您可以使用MongoDB脚本语言直接删除它:
db.mycoll.remove({_id:'your_id_here'});
答案 2 :(得分:2)
deleteMany()
会更有效吗?我最近发现,{1}在100米文档集中的600万个文档中速度很慢。文档(https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany)
remove()
答案 3 :(得分:1)
在cmd
db.users.remove({" _id":ObjectId(" 5a5f1c472ce1070e11fde4af")});
如果您使用node.js,请编写此代码
User.remove({ _id: req.body.id },, function(err){...});
答案 4 :(得分:0)
如果有大量记录,我建议分页。
首先:获取要删除的数据计数:
-------------------------- COUNT --------------------------
var query= {"FEILD":"XYZ", 'DATE': {$lt:new ISODate("2019-11-10")}};
db.COL.aggregate([
{$match:query},
{$count: "all"}
])
第二:开始逐块删除:
-------------------------- DELETE --------------------------
var query= {"FEILD":"XYZ", 'date': {$lt:new ISODate("2019-11-10")}};
var cursor = db.COL.aggregate([
{$match:query},
{ $limit : 5 }
])
cursor.forEach(function (doc){
db.COL.remove({"_id": doc._id});
});
这应该更快:
var query={"FEILD":"XYZ", 'date': {$lt:new ISODate("2019-11-10")}};
var ids = db.COL.find(query, {_id: 1}).limit(5);
db.tags.deleteMany({"_id": { "$in": ids.map(r => r._id)}});