统计 MongoDB 中的记录
本文讨论 MongoDB 中的运算符、聚合运算符以及计算总记录数的不同方法。
MongoDB 中的操作
CRUD 操作是用户界面的概念,允许用户浏览、搜索和更改数据库中的对象。
MongoDB 文档通过连接到服务器、查询适当的文档、然后在将数据发送回数据库进行处理之前转换它们来更改。 CRUD 是一个数据驱动的过程,它使用 HTTP 动作动词对其进行标准化。
- 创建 - 用于在 MongoDB 数据库中插入新文档。
- 读取 - 用于查询数据库中的文档。
- 更新 - 用于修改数据库中的现有文件。
- 删除 - 删除数据库中的文档。
MongoDB 中的聚合操作
它是一种数据处理操作,由多个阶段组成,这些阶段对分组数据执行许多操作以产生单个结果。 以下是执行聚合操作的三个选项。
-
聚合管道——文档通过多阶段管道提供,将它们集成到一个输出中。 MongoDB聚合过程分为多个阶段。
下面给出了一个例子
db.collection_name.aggregate([ //First stage { $match: { status: "" } }, //Second stage { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, //Third Stage { $sort : {sort_field: -1 }} ])
- Single Purpose Aggregation Methods - 单一用途聚合方法很简单,但它们缺乏聚合管道的功能。
- Map-Reduce - Map-reduce 操作自 MongoDB 5.0 以来已被弃用。 相反,使用聚合管道。
MongoDB 中的 $count
将文档发送到下一步,并计算它已收到的记录数。
行为:
下面的 $group + $project 序列等于 $count 阶段。
db.collection.aggregate( [
{ $group: { _id: null, myCount: { $sum: 1 } } },
{ $project: { _id: 2 } }
] )
其中 myCount 表示,输出字段包含计数。 您可以为输出字段指定一个不同的名称。
例子:
名为 scores 的集合具有给定的文档。
{ "_id" : 1, "subject" : "English", "score" : 88 }
{ "_id" : 2, "subject" : "English", "score" : 92 }
{ "_id" : 3, "subject" : "English", "score" : 97 }
{ "_id" : 4, "subject" : "English", "score" : 71 }
{ "_id" : 5, "subject" : "English", "score" : 79 }
{ "_id" : 6, "subject" : "English", "score" : 83 }
以下聚合操作有两个阶段。
- $match阶段过滤掉score值小于等于80的文档,让score大于80的文档进入下一阶段。
- $count 步骤计算聚合管道中剩余的文档数,并将结果存储在名为 passing_scores 的变量中。
db.scores.aggregate(
[
{
$match: {
score: {
$gt: 80
}
}
},
{
$count: "passing_scores"
}
]
)
该操作返回以下结果。
{ "passing_scores" : 4 }
对于获取 1000 条记录,这平均需要 2 毫秒,是最快的方法。
MongoDB 中的 db.collection.count()
返回集合或视图中与 find() 查询匹配的记录数。 db.collection.count()
函数计算并提供匹配查询的结果数,而不是 find() 过程。
行为:
在事务中,您不能使用计数或 shell 工具 count() 和 db.collection.count()。
分片集群
如果存在孤立文档或正在进行块迁移,则在分片集群上使用不带查询谓词的 db.collection.count() 可能会导致错误计数。
在分片集群上使用 db.collection.aggregate()
函数来防止这些情况。
要对文档进行计数,请使用 $count 步骤。 例如,以下过程对集合中的文档进行计数。
db.collection.aggregate( [
{ $count: "myCount" }
])
$count 阶段等于以下 $group + $project 序列。
db.collection.aggregate( [
{ $group: { _id: null, count: { $sum: 1 } } }
{ $project: { _id: 0 } }
] )
索引使用
考虑具有以下索引的集合。
{ a: 1, b: 1 }
在进行计数时,如果查询:MongoDB 只能使用索引返回计数:
- 可以使用索引,
- 仅包含索引键的条件,并且
- 谓词访问单个连续范围的索引键
例如,仅给定索引,以下过程可以返回计数。
db.collection.find( { a: 5, b: 5 } ).count()
db.collection.find( { a: { $gt: 5 } } ).count()
db.collection.find( { a: 5, b: { $gt: 10 } } ).count()
假设查询可能使用一个索引,但谓词没有到达一个连续的索引键范围。 该查询还对索引外的字段有条件。
在这种情况下,MongoDB 除了利用索引提供计数外,还必须读取文档。
db.collection.find( { a: 6, b: { $in: [ 1, 2, 3 ] } } ).count()
db.collection.find( { a: { $gt: 6 }, b: 5 } ).count()
db.collection.find( { a: 5, b: 5, c: 8 } ).count()
在这种情况下,MongoDB 在初始读取期间将文档分页到内存中,从而提高后续调用相同计数操作的速度。
意外停机时的准确性
在使用 Wired Tiger 存储引擎的 mongod 不正常关闭后,count() 提供的计数统计可能是错误的。
在最后一个检查点和不正常关闭之间,执行的插入、更新或删除操作的数量决定了漂移量。
检查点平均每 60 秒发生一次。 另一方面,具有非默认 -syncdelay 选项的 mongod 实例可能有更多或更少的检查点。
要在不正常关闭后恢复统计信息,请对 mongod 上的每个集合运行验证。
不正常关机后:
- validate 使用最新值更新 collStats 输出中的计数统计信息。
- 其他统计信息,如 collStats 输出中插入或删除的文档数量,都是估计值。
客户端断开
从 MongoDB 4.2 开始,如果发出 db.collection.count() 的客户端在操作完成之前断开连接,MongoDB 会使用 killOp 将 db.collection.count() 标记为终止。
计算集合中的所有文档
要计算订单集合中所有记录的数量,请使用以下操作。
db.orders.count()
此操作等效于以下操作。
db.orders.find().count()
计算匹配查询的所有文档
计算 orders 集合中有多少文档具有大于 new Date('01/01/2012') 的字段 ord_dt。
db.orders.count( { ord_dt: { $gt: new Date('01/01/2012') } } )
该查询等效于以下内容。
db.orders.find( { ord_dt: { $gt: new Date('01/01/2012') } } ).count()
MongoDB 按计数分组
MongoDB 中每个文档的 _id
列已按值分配了一个唯一的组。 然后聚合技术处理数据,产生计算结果。
下面是一个例子。
此设置将用于本文中提供的所有代码示例。
db={
"data": [
{
"_id": ObjectId("611a99100a3322fc1bd8c38b"),
"fname": "Tom",
"city": "United States of America",
"courses": [
"c#",
"asp",
"node"
]
},
{
"_id": ObjectId("611a99340a3322fc1bd8c38c"),
"fname": "Harry",
"city": "Canada",
"courses": [
"python",
"asp",
"node"
]
},
{
"_id": ObjectId("611a99510a3322fc1bd8c38d"),
"fname": "Mikky",
"city": "New Zealand",
"courses": [
"python",
"asp",
"c++"
]
},
{
"_id": ObjectId("611b3e88a60b5002406571c3"),
"fname": "Ron",
"city": "United Kingdom",
"courses": [
"python",
"django",
"node"
]
}
]
}
查询上述数据库使用的是:
db.data.aggregate([
{
$group: {
_id: "ObjectId",
count: {
$count: {}
}
}
}
])
查看此代码段的工作情况。
MongoDB 按计数排序分组
本节使用$sortByCount,与$group + $sort 作用相同。 它可以按升序和降序对一组人进行排序和计数。
下面给出了一个示例查询。 本示例中已将一些文档添加到数据集合中,并使用 find() 方法确定它包含多少条目。
以下将是对 find() 的查询。
db.data.find()
您可以从此链接访问此查询的执行。
下一步是撤消课程数组并使用 $sortByCount 函数计算添加到每个课程的记录数。
db.data.aggregate([
{
$unwind: "$courses"
},
{
$sortByCount: "$courses"
}
])
查看此查询在上述数据库配置下的工作情况。 这是通过对数组进行计数并对其进行排序来对 MongoDB 组进行最直接的处理。
MongoDB 通过统计多个字段来分组
MongoDB 的 aggregate()
函数可能会计算多个字段。 因此,使用 $count 对字段进行计数。
下面是一个时间戳仅用于一个条目的示例。 本例中student集合中可以保存一些文档,你可以使用find()方法查看你有多少文档。
db.student.aggregate([ {$group: {_id: {name:"$name",
timestamp:"$timestamp" }}},
{$count:"timestamp"}
])
MongoDB 按日期和计数分组
当您需要统计特定日期的文档时,您可以使用计数聚合并统计特定日期的文档。
这是一个例子。 在此示例中,您将学习计算 2021 年每一天的总销量和销售数量。
您可以在销售集合中包含产品 ID、项目名称、价格、数量和日期字段。 可以使用 find() 方法获取文档。
db=
{
"_id" : 1,
"item" : "abc",
"price" : NumberDecimal("10"),
"quantity" : 2,
"date" : ISODate("2021-03-01T08:00:00Z")
}
{
"_id" : 2,
"item" : "jkl",
"price" : NumberDecimal("20"),
"quantity" : 1,
"date" : ISODate("2021-03-01T09:00:00Z")
}
{
"_id" : 3,
"item" : "xyz",
"price" : NumberDecimal("5"),
"quantity" : 10,
"date" : ISODate("2021-03-15T09:00:00Z")
}
{
"_id" : 4,
"item" : "xyz",
"price" : NumberDecimal("5"),
"quantity" : 20,
"date" : ISODate("2021-04-04T11:21:39.736Z")
}
{
"_id" : 5,
"item" : "abc",
"price" : NumberDecimal("10"),
"quantity" : 10,
"date" : ISODate("2021-04-04T21:23:13.331Z")
}
查询上述配置将是:
db.date.aggregate([
{
$match : { "date": { $gte: new ISODate("2021-01-01"), $lt: new ISODate("2015-01-01") } }
},
{
$group : {
_id : { $dateToString: { format: "%Y-%m-%d", date: "$date" } },
totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } },
count: { $sum: 1 }
}
},
{
$sort : { totalSaleAmount: -1 }
}
])
现在使用 count 和 field 命令查询单个字段和多个字段组。
-
单字段分组依据和计数
db.Request.aggregate([ {"$group" : {_id:"$source", count:{$sum:1}}} ])
-
多个字段分组和计数
db.Request.aggregate([ {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}} ])
-
多个字段分组依据并使用字段排序计数
db.Request.aggregate([ {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}}, {$sort:{"_id.source":1}} ])
-
多个字段分组依据并使用计数进行排序
db.Request.aggregate([ {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}}, {$sort:{"count":-1}} ])
MongoDB 中的 .toArray() 方法
toArray()
函数返回一个包含游标中所有文档的数组。 该过程多次遍历游标,将所有文档加载到 RAM 中并耗尽指针。
考虑以下示例,它使用 toArray()
函数来转换 find() 方法返回的游标。
var allProductsArray = db.products.find().toArray();
if (allProductsArray.length > 0) { printjson (allProductsArray[0]); }
变量 allProductsArray 保存由 toArray()
返回的文档数组。 获取 1000 条记录,平均需要 18 毫秒。
MongoDB 中的 .itcount()
计算游标中剩余的文档数。
itcount()
与 cursor.count()
类似,但它不是在新迭代器上运行查询,而是在现有迭代器上执行它,耗尽其内容。
itcount()
方法的原型形式如下。
db.collection.find(<query>).itcount()
获取 1000 条记录,平均需要 14 毫秒。
这篇文章详细讨论了操作,也讨论了聚合操作。 首先,通过代码段简要讨论了不同类型的聚合函数。
然后group by和count讨论了,其中讨论了排序,查找,多字段。 然后讨论了统计MongoDB中记录的不同方法。
相关文章
MongoDB 中的 $unset 运算符
发布时间:2023/05/10 浏览次数:135 分类:MongoDB
-
本文将讨论 $unset 运算符在 MongoDB 中的工作原理。 此外,我们将演示使用此运算符从 MongoDB 集合中的所有文档中删除一个字段。MongoDB 中的 $unset 运算符 $unset 是用于从实体中删除字段的运算符。
MongoDB 中的 $ne 运算符
发布时间:2023/05/10 浏览次数:82 分类:MongoDB
-
本文将讨论 $ne 运算符如何在 MongoDB 中工作。 另外,我们会列举它与$not操作符的区别。MongoDB 中的 $ne 运算符 $ne 是MongoDB中的一个运算符,代表不等于。
MongoDB $Set 运算符
发布时间:2023/05/10 浏览次数:54 分类:MongoDB
-
在本文中,我们将学习如何使用 $set 运算符部分更新 MongoDB 中的对象,以便新对象与现有对象重叠/合并。
MongoDB 中 $push 和 $addToSet 的区别
发布时间:2023/05/10 浏览次数:103 分类:MongoDB
-
这篇指导文章将告诉您什么是 MongoDB 中的运算符以及它们是如何描述的。 此外,对 $push 和 $addToSet 运算符进行了简要的详细说明。 $push 和 $addToSet 之间的区别通过代码段详细说明。
在 MongoDB 中按日期对集合进行排序
发布时间:2023/05/10 浏览次数:150 分类:MongoDB
-
在本 MongoDB 教程中,讨论了在 MongoDB 中对集合进行排序的问题。 简要说明了对数据库中的集合进行排序的不同方法。在 MongoDB 中使用 sort() 函数
在 MongoDB 中更新用户密码
发布时间:2023/05/10 浏览次数:156 分类:MongoDB
-
本文将讨论如何更新 MongoDB 数据库的用户密码,并且我们还将看到一个与该主题相关的示例以使其更容易。在 MongoDB 中更新用户密码
比较 MongoDB 中的字段
发布时间:2023/04/21 浏览次数:51 分类:MongoDB
-
在本文中,我们将了解如何比较 MongoDB 中的两个字段。 此外,我们将看到一个相关的示例和解释,以使主题更容易理解。
清除或删除 MongoDB 中的集合
发布时间:2023/04/21 浏览次数:147 分类:MongoDB
-
本篇文章将告诉大家如何删除 MongoDB 数据库中的集合以及删除 MongoDB 中的集合的不同方法。
向 MongoDB 集合中的每个文档添加新字段
发布时间:2023/04/21 浏览次数:107 分类:MongoDB
-
您将在这篇文章中了解 $set 和 $setOnInsert 操作。 此外,利用这两个运算符,快速描述了向 MongoDB 中的集合添加字段的挑战。