如何删除文档中的 N 个文档

在我的集合中,文档包含状态和时间戳等键。当我想找到最新的十个文件,然后我写下面的查询

db.collectionsname.find().sort({"timestamp"-1}).limit(10)

这个查询给了我我想要的结果,但是当我想删除最新的十个文档时,我正在写下面的查询

db.collectionsname.remove({"status":0},10).sort({"timestamp":-1})

但它显示了以下错误 TypeError: Cannot call method 'sort' of undefined 同样,我也写了如下相同的查询 db.collectionsname.remove({"status":0},10) 它只删除一个文档。那么我如何编写一个查询来删除十个最新的文档并按时间戳进行排序呢?

65632 次浏览

使用 removefindAndModify时不能设置限制。因此,如果您想精确地限制删除的文档数量,您需要分两个步骤来完成。

db.collectionName.find({}, {_id : 1})
.limit(100)
.sort({timestamp:-1})
.toArray()
.map(function(doc) { return doc._id; });  // Pull out just the _ids

然后将返回的 _id传递给 delete 方法:

db.collectionName.remove({_id: {$in: removeIdsArray}})

仅供参考: 您不能从有上限的集合中删除文档。

下面的查询将查找和删除收集的最新10个文档:-

db.collectionsname.findAndModify({
query: { 'status':0 },
sort: { 'timestamp': -1 },
limit: 10,
remove: true
});

另一种方法是编写一个 python 脚本。

from pymongo import MongoClient


def main():
local_client = MongoClient()
collection = local_client.database.collection
cursor = collection.find()
total_number_of_records = 10000


for document in cursor:
id = document.get("_id")


if total_number_of_records == 100:
break


delete_query = {"_id": id}
collection.delete_one(delete_query)


total_number_of_records -= 1


if __name__ == "__main__":
# execute only if run as a script
main()

设 N 为要删除的记录数。

    db.collectionName.find().limit(N).forEach(doc =>
{
db.collectionName.remove({_id:doc._id})
}
)

Query sql 是

db.order.find({"业务员姓名" : "吊炸天"},{"业务员编号":0}).sort({ "订单时间" : -1 })

结果就是

{
"_id" : ObjectId("5c9c875fdadfd961b4d847e7"),
"推送ID" : "248437",
"订单时间" : ISODate("2019-03-28T08:35:52Z"),
"订单状态" : "1",
"订单编号" : "20190328163552306694",
"业务员姓名" : "吊炸天"
}
{
"_id" : ObjectId("5c9c875fdadfd961b4d847e8"),
"推送ID" : "248438",
"订单时间" : ISODate("2019-03-28T08:35:52Z"),
"订单状态" : "1",
"订单编号" : "20190328163552178132",
"业务员姓名" : "吊炸天"
}
{
"_id" : ObjectId("5c9c875fdadfd961b4d847e5"),
"推送ID" : "248435",
"订单时间" : ISODate("2019-03-28T08:35:51Z"),
"订单状态" : "1",
"订单编号" : "20190328163551711074",
"业务员姓名" : "吊炸天"
}
{
"_id" : ObjectId("5c9c875fdadfd961b4d847e6"),
"推送ID" : "248436",
"订单时间" : ISODate("2019-03-28T08:35:51Z"),
"订单状态" : "1",
"订单编号" : "20190328163551758179",
"业务员姓名" : "吊炸天"
}

现在删除3和4的数据

var name = ["吊炸天"]
var idArray = db.order.find({"业务员姓名" : {$in:name}},{"订单编号":1,})
.sort({ "订单时间" : -1 })
.skip(2)
.map(function(doc){return doc.订单编号})


db.order.deleteMany({"订单编号":{$in:idArray}})

结果如下:

{
"acknowledged" : true,
"deletedCount" : 2
}

要删除您集合中的 N 个文档 myCollection:

db.getCollection('myCollection').find({}).limit(N).forEach(function(doc){
db.getCollection('myCollection').remove({_id: doc._id});
})

您可以将查找查询映射的输出管道化,以使用 _id,并根据 $in查询执行删除操作,例如:

db.collection.remove({_id:
{ $in: db.collection.find().sort({timestamp:-1}).limit(100).map(a => a._id) }
})

下面是另一种方法:

步骤1: 临时收集的排序、限制和 $out 文档

db.my_coll.aggregate([
{ $sort: { _id: - 1} },
{ $limit: 10000 },
{ $out: 'my_coll_temp' }
])

步骤2: 从原始集合中删除所有文档(不删除,因为这样可以保留索引)。此外,这一步骤可能会使这种方法的通用性降低,因为删除可能并不总是可能的。

db.my_coll.remove({})

步骤3: 将文件从临时收集移回到原始收集

db.my_coll_temp.aggregate([ { $out: 'my_coll' } ])

步骤4: 删除临时收集

db.my_coll_temp.drop()

工作解决方案 (受上述答案启发) :

(为删除大量的记录,$in运营商有一个限制,所以这是最终的解决方案) 删除1,000,000条记录的示例

var ITERATIONS=1000;
var LIMIT=1000;
for(i=0; i<ITERATIONS; i++) {
arr = db.MyCollection.find({}, {_id : 1}).limit(LIMIT).toArray().map(function(doc) { return doc._id; });
db.MyCollection.remove({_id: {$in: arr}});
// sleep(1);  // Optional for not loading mongo in case of huge amount of deletions
}

您可以在 mongo shell 或 Robomongo 3T 中运行它

我发现的方法是:

        let uid = "your_user";


let a = await db
.collection(`notifications`)
.find({
owner: uid,
})
.sort({ _id: -1 })
.skip(1000)
.limit(1)
.toArray();


if (a.length > 0) {
let _id = new ObjectId(a[0]._id);
db.collection(
`notifications`
).deleteMany({
owner: uid,
_id: { $lt: _id },
});
}

说明: ‘ a’变量获取要删除旧条目的最后一个条目的 _ id。可以使用“跳过”指定 n 值。示例: 您有5000个条目,但是您想保留400个新条目,只需将跳过设置为“400”。在本例中,我们使用 _ id 进行排序,但是您可以使用所需的内容。您可以使用 find 来筛选结果,使其与所需的结果完全匹配。

算法的后半部分执行删除操作。使用相同的筛选器(owner: uid)匹配第一个查找,并删除许多小于“ _ id”的内容。

您还可以在此代码块之前使用“ count”if 语句来检查是否有必要,以避免服务器浪费。