MongoDB 游标详解及实例代码

1. MongoDB游标介绍

MongoDB的游标是一种机制,用于在查询结果集中以分批的方式处理大量数据。在处理大数据集合时,游标可以很好地提高查询效率,避免一次读入全部结果,占用过多内存。MongoDB的游标是一种类似于迭代器的数据结构,使得可以使用next()方法逐个访问查询结果集合的每一条记录。

1.1 游标类型

cursor有几种不同类型的游标,取决于如何获取游标和它们的初始状态。以下是几种常见的类型。

非Tailable游标:

非Tailable游标是默认类型,它在初始状态下只指向查询结果集的第一条记录,需要使用next()方法进行迭代。一旦游标到达集合的末端,它不会再次循环回到集合的开头。如果该查询是一个多个批次的输出,并且您需要多次访问结果集,您应该使用可遍历的游标。

Tailable游标:

Tailable游标是可以在集合末尾处迭代,以查看接收到的数据是否新增的一种非阻塞型的游标。 它通常是在日志文件中使用,并且Estimate for total 或limit()和skip()等操作是无效的,因为在新增数据产生时游标会被自动更新。即 ,当游标耗尽结果集是,MongoDB会等待新的数据到达,这使得Tailable游标非常适合用于日志文件之类的应用程序,以最新的数据为基础进行分析。

2. 游标常用操作

2.1 sort()方法

sort()方法可以用于在游标中指定一个排序的字段以及排序的顺序。如果未指定排序顺序,将默认按顺序进行升序排序。示例如下:

db.collection.find().sort({field: order})

其中field为排序的字段,order为排序的顺序,可以是1或-1。1表示升序,-1表示降序。例如,按照年龄和工作经验升序排序:

db.employee.find().sort({age: 1, years_of_experience: 1})

2.2 limit()方法

limit()方法用于限制查询结果集合的数量。它接受一个数字参数,表示查询返回的最大文档数。如果需要查询前10个文档,则可以使用limit(10):

db.collection.find().limit(number)

其中number表示文档数目。例如,查询前10条文档:

db.employee.find().limit(10)

2.3 skip()方法

skip()方法用于跳过查询结果集的前几个文档。它接受一个数字参数,表示跳过的文档数目。例如,跳过前20个文档并返回后10个文档:

db.collection.find().skip(number).limit(number)

其中skip(number)指定了需要跳过的文档数目,limit(number)指定了返回文档的上限。例如,查询21-30个文档:

db.employee.find().skip(20).limit(10)

2.4 forEach()方法

forEach()方法可以对游标中的每个文档应用一个自定义函数。每个文档都作为该函数的输入参数传递。例如,计算员工平均工资:

db.employee.find().forEach(function(employee) {

var totalSalary = employee.salary.reduce((a, b) => a + b, 0);

var averageSalary = totalSalary / employee.salary.length;

print(employee.name + "的平均工资是:" + averageSalary + "元");

})

3. 游标实例

假设我们有一个名为user的集合,其中包含以下数据:

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb5f"), "name" : "Andy", "age" : 25, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb60"), "name" : "Bob", "age" : 27, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb61"), "name" : "Cathy", "age" : 22, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb62"), "name" : "David", "age" : 30, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb63"), "name" : "Ella", "age" : 21, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb64"), "name" : "Frank", "age" : 29, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb65"), "name" : "Grace", "age" : 19, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb66"), "name" : "Harry", "age" : 32, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb67"), "name" : "Iris", "age" : 24, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb68"), "name" : "Jack", "age" : 28, "gender" : "male" }

3.1 查询年龄大于25的男性员工

db.user.find({ "age": {"$gt": 25}, "gender": "male"})

返回结果如下:

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb60"), "name" : "Bob", "age" : 27, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb62"), "name" : "David", "age" : 30, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb64"), "name" : "Frank", "age" : 29, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb68"), "name" : "Jack", "age" : 28, "gender" : "male" }

3.2 按年龄升序排序

db.user.find().sort({ age: 1})

返回结果如下:

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb65"), "name" : "Grace", "age" : 19, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb63"), "name" : "Ella", "age" : 21, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb67"), "name" : "Iris", "age" : 24, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb5f"), "name" : "Andy", "age" : 25, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb61"), "name" : "Cathy", "age" : 22, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb67"), "name" : "Iris", "age" : 24, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb60"), "name" : "Bob", "age" : 27, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb68"), "name" : "Jack", "age" : 28, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb64"), "name" : "Frank", "age" : 29, "gender" : "male" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb62"), "name" : "David", "age" : 30, "gender" : "male" }

3.3 查询前3个女性员工

db.user.find({ "gender": "female"}).limit(3)

返回结果如下:

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb65"), "name" : "Grace", "age" : 19, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb61"), "name" : "Cathy", "age" : 22, "gender" : "female" }

{ "_id" : ObjectId("5f9ac55cff1fc7f350b1cb63"), "name" : "Ella", "age" : 21, "gender" : "female" }

数据库标签