15

我有一个查询,它选择要删除的文档。现在,我手动删除它们,就像这样(使用 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每个键值最多,只留下最新的记录。它是这样工作的:

  1. MR 数据(key, count)对。
  2. 遍历所有对count > max_group_size
  3. 按 查询数据key,同时按时间戳升序排序(最早的在前)并将结果限制为count - max_group_size最旧的记录
  4. 删除每一条找到的记录。

如您所见,这完成了将重复项减少到最多 N 个最新记录的任务。所以,最后两个步骤是foreach-found-remove,这是我的问题的重要细节,它改变了一切,我必须更具体 - 抱歉。

现在,关于集合删除命令。它确实接受查询,但我的包括排序和限制。我可以用删除来做吗?好吧,我试过了:

mydb.static.find(key, limit = group_size - max_group_size, sort=[('test_date', ASCENDING)])

这次尝试惨败。此外,它似乎搞砸了 mongo。观察:

C:\dev\poc\SDR>python FilterOoklaData.py
bad offset:0 accessing file: /data/db/ookla.0 - consider repairing database

不用说,foreach-found-remove 方法有效并产生了预期的结果。

现在,我希望我已经提供了足够的背景信息,并且(希望)已经恢复了我失去的荣誉。

4

5 回答 5

37

您可以使用查询来删除所有匹配的文档

var query = {name: 'John'};
db.collection.remove(query);

但是要小心,如果匹配文档的数量很高,您的数据库可能会变得不那么响应。通常建议以较小的块删除文档。

假设您有 100k 个文档要从集合中删除。执行 100 次删除 1k 文档的查询比执行 1 次删除所有 100k 文档的查询要好。

于 2012-04-04T15:24:45.103 回答
11

您可以使用 MongoDB 脚本语言直接删除它:

db.mycoll.remove({_id:'your_id_here'});
于 2012-04-04T15:24:04.597 回答
2

deleteMany()更有效率吗?我最近发现,remove()对于 100m 文档集合中的 6m 文档,这非常慢。文档位于(https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany

db.collection.deleteMany(
   <filter>,
   {
      writeConcern: <document>,
      collation: <document>
   }
)
于 2017-11-09T01:05:31.407 回答
1

如果有大量记录,我建议分页。

第一:获取要删除的数据数量:

-------------------------- 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)}});
于 2019-11-20T17:49:18.657 回答
0

运行此查询cmd

db.users.remove({"_id": ObjectId("5a5f1c472ce1070e11fde4af")});

如果您使用的是 node.js,请编写此代码

User.remove({ _id: req.body.id },, function(err){...});
于 2018-01-17T12:28:20.203 回答