迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 数据库 > MongoDB >

统计 MongoDB 中的记录

作者:迹忆客 最近更新:2023/05/07 浏览次数:

本文讨论 MongoDB 中的运算符、聚合运算符以及计算总记录数的不同方法。


MongoDB 中的操作

CRUD 操作是用户界面的概念,允许用户浏览、搜索和更改数据库中的对象。

MongoDB 文档通过连接到服务器、查询适当的文档、然后在将数据发送回数据库进行处理之前转换它们来更改。 CRUD 是一个数据驱动的过程,它使用 HTTP 动作动词对其进行标准化。

  1. 创建 - 用于在 MongoDB 数据库中插入新文档。
  2. 读取 - 用于查询数据库中的文档。
  3. 更新 - 用于修改数据库中的现有文件。
  4. 删除 - 删除数据库中的文档。

MongoDB 中的聚合操作

它是一种数据处理操作,由多个阶段组成,这些阶段对分组数据执行许多操作以产生单个结果。 以下是执行聚合操作的三个选项。

  1. 聚合管道——文档通过多阶段管道提供,将它们集成到一个输出中。 MongoDB聚合过程分为多个阶段。

    下面给出了一个例子

    db.collection_name.aggregate([
    //First stage
    { $match: { status: "" } },
    //Second stage
    { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
    //Third Stage
     { $sort : {sort_field: -1 }}
    ])
    
  2. Single Purpose Aggregation Methods - 单一用途聚合方法很简单,但它们缺乏聚合管道的功能。
  3. 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 }

以下聚合操作有两个阶段。

  1. $match阶段过滤掉score值小于等于80的文档,让score大于80的文档进入下一阶段。
  2. $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 只能使用索引返回计数:

  1. 可以使用索引,
  2. 仅包含索引键的条件,并且
  3. 谓词访问单个连续范围的索引键

例如,仅给定索引,以下过程可以返回计数。

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 上的每个集合运行验证。

不正常关机后:

  1. validate 使用最新值更新 collStats 输出中的计数统计信息。
  2. 其他统计信息,如 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: {}
      }
    }
  }
])

查看此代码段的工作情况。

group by


MongoDB 按计数排序分组

本节使用$sortByCount,与$group + $sort 作用相同。 它可以按升序和降序对一组人进行排序和计数。

下面给出了一个示例查询。 本示例中已将一些文档添加到数据集合中,并使用 find() 方法确定它包含多少条目。

以下将是对 find() 的查询。

db.data.find()

您可以从此链接访问此查询的执行。

下一步是撤消课程数组并使用 $sortByCount 函数计算添加到每个课程的记录数。

db.data.aggregate([
  {
    $unwind: "$courses"
  },
  {
    $sortByCount: "$courses"
  }
])

查看此查询在上述数据库配置下的工作情况。 这是通过对数组进行计数并对其进行排序来对 MongoDB 组进行最直接的处理。

group by 2


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 命令查询单个字段和多个字段组。

  1. 单字段分组依据和计数
    db.Request.aggregate([
     {"$group" : {_id:"$source", count:{$sum:1}}}
    ])
    
  2. 多个字段分组和计数
    db.Request.aggregate([
     {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}}
    ])
    
  3. 多个字段分组依据并使用字段排序计数
    db.Request.aggregate([
     {"$group" : {_id:{source:"$source",status:"$status"}, count:{$sum:1}}},
     {$sort:{"_id.source":1}}
    ])
    
  4. 多个字段分组依据并使用计数进行排序
    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中记录的不同方法。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

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 中的集合的不同方法。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便