首页 > 编程笔记 > MongoDB 阅读:15

MongoDB集合操作大全(附带实例)

MongoDB 提供了诸多有关集合或视图操作的方法,常见的方法如下表所示:

表:MongoDB 中集合操作相关的方法
方法名 描述
db.collection.aggregate() 聚合管道
db.collection.bulkWrite() 批量操作
db.collection.count() 统计集合或视图的文档数量(MongoDB 4.0 之后该方法已过时)
db.collection.countDocuments() 返回集合或视图中的文档计数
db.collection.createIndex() 创建一个索引
db.collection.createIndexes() 创建一个或多个索引
db.collection.dataSize() 返回集合大小
db.collection.deleteOne() 删除一个文档
db.collection.deleteMany() 删除多个文档
db.collection.distinct() 指定字段去重
db.collection.drop() 删除集合
db.collection.dropIndex() 删除指定索引
db.collection.dropIndexes() 删除多个索引
db.collection.estimatedDocumentCount() 统计集合或视图的文档数量
db.collection.explain() 返回有关各种方法的查询执行的信息
db.collection.find() 查询视图或集合中的数据,返回游标信息
db.collection.findOneAndModify() 修改并返回单个文档,支持原子操作
db.collection.findOne() 查询并返回单个文档
db.collection.findOneAndDelete() 查询文档并删除
db.collection.findOneAndReplace() 查询文档并替换
db.collection.findOneAndUpdate() 查询文档并更新
db.collection.getIndexes() 返回索引列表
db.collection.getShardDistribution() 对于分片集群中的集合,返回分片数据
db.collection.getShardVersion() 分片集群的内部诊断方法
db.collection.hideIndex() 从查询计划器隐藏索引
db.collection.insertOne() 插入单个文档
db.collection.insertMany() 插入多个文档
db.collection.isCapped() 查询集合是否为固定上限的集合
db.collection.latencyStats() 返回集合的延迟统计信息
db.collection.mapReduce() 进行 map-reduce 风格的数据集合
db.collection.reIndex() 重建集合中的所有索引
db.collection.remove() 删除集合中的所有文档
db.collection.renameCollection() 修改集合名称
db.collection.replaceOne() 替换文档内容
db.collection.stats() 返回集合的统计信息
db.collection.storageSize() 集合存储字节数
db.collection.totalIndexSize() 返回集合中索引的大小
db.collection.totalSize() 返回集合的总大小
db.collection.unhideIndex() 从查询计划中隐藏索引
db.collection.updateOne() 修改单个文档
db.collection.updateMany() 修改多个文档
db.collection.watch() 创建集合的变化流
db.collection.validate() 对集合进行诊断操作

这些方法涵盖文档的查询、插入、更新和删除,集合统计,索引操作等方面。

MongoDB集合操作

1、统计集合或视图的文档数量

MongoDB 提供了两个关于统计文档数量的方法:
db.collection.countDocuments(query, options)
db.collection.estimatedDocumentCount(options)
countDocuments(query, options) 是通过实际存储的数据,利用 $sum 表达式和 $group 聚合阶段进行统计计算的。此方法会扫描整个集合,因此存在一定性能风险。在没有精确的过滤条件时,该方法的查询效率较低。

其中,query 参数为查询条件,如果查询所有的数据,则该参数传入空值。options 参数为可选参数,可接受以下 4 个值:
而 estimatedDocumentCount(options) 是通过元数据来统计文档数量的,因此在查询整个集合时,该方法的效率更高。它仅接收一个参数,即 maxTimeMS(最大查询时间限制值)。但需要注意的是,这个方法在特定情况下可能与实际文档数量存在差异,例如在意外的实例停机或孤儿文档的情况下,可能会导致统计数据不一致。

【实例】对比两个统计方法的查询效率。通过脚本来计算执行两个统计方法所需的时间,对比两个方法的查询效率。脚本内容如下:
// 设置开始时间
var startTime = new Date();
// 执行查询操作
var result = db.products.countDocuments({});
// 设置结束时间
var endTime = new Date();
// 计算查询所需的时间(单位为毫秒)
var queryTime = endTime - startTime;
print("countDocuments所需时间:" + queryTime + "ms");
// 设置开始时间
var startTime2 = new Date();
// 执行查询操作
var result2 = db.products.estimatedDocumentCount();
// 设置结束时间
var endTime2 = new Date();
// 计算查询所需的时间(单位为毫秒)
var queryTime2 = endTime2 - startTime2;
print("estimatedDocumentCount所需时间:" + queryTime2 + "ms");
执行结果为:

shopping> .editor
// Entering editor mode (Ctrl+D to finish, Ctrl+C to cancel)
// 设置开始时间
var startTime = new Date();
// 执行查询操作
var result = db.products.countDocuments({});
// 结束时间
var endTime = new Date();
// 计算查询所需的时间(单位为毫秒)
var queryTime = endTime - startTime;
print("countDocuments所需时间:" + queryTime + "ms");
// 设置开始时间
var startTime2 = new Date();
// 执行查询操作
var result2 = db.products.estimatedDocumentCount();
// 结束时间
var endTime2 = new Date();
// 计算查询所需的时间(单位为毫秒)
var queryTime2 = endTime2 - startTime2;
print("estimatedDocumentCount所需时间:" + queryTime2 + "ms");
countDocuments所需时间:13ms
estimatedDocumentCount所需时间:6ms

从运行结果可以看到,在数据量小时,两个方法的差异不太大,但已有明显差异,随着数据量的增长,该差距会越来越大。因此,在实际应用中,要根据具体场景选择更适合的方法。

2、批量操作bulkWrite

批量写入方法格式如下:
db.collection.bulkWrite(
    [ <operation 1>, <operation 2>, ... ],
    {
        writeConcern : <document>,
        ordered : <boolean>
    }
)
第一个参数为 operations,即操作名称的数组集合,可支持的操作有 insertOne、updateOne、updateMany、deleteOne、deleteMany、replaceOne。

第二个参数为 writeConcern,即相关文档,该参数为可选参数。如果不传入的话,会使用默认值,路径为 /includes/extracts/transactions-operations-write-concern.rst。注意,如果在事务中运行该方法,则不能传递 writeConcern 参数。

第三个参数为 ordered,布尔型可选参数,指明数据库是否按顺序执行操作,默认为 true。

1) 使用bulkWrite插入数据

语法格式如下:
db.collection.bulkWrite([
{
    insertOne:{"document:<document>"}
   
])

【实例】使用 bulkWrite 方法插入数据。向 shopping 数据库的 products 中插入图书商品信息。语句如下:
db.products.bulkWrite([
    { insertOne : { "document" : {"name":"活着","author":"余华","press":"北京十月文艺出版社","publishTime":"2021-10-01","type":"book","comments":"1332375","price":45,"discount":"31","ebookPrice":29} } }
])
执行结果为:
shopping> db.products.bulkWrite([
...    { insertOne : { "document" : { "name" : "活着", "author" : "余华", "press" : "北京十月文艺出版社", "publishTime" : "2021-10-01", "type" : "book", "comments" : "1332375", "price" : 45, "discount" : "31", "ebookPrice" : 29 } } }
... ])
{
    acknowledged: true,
    insertedCount: 1,
    insertedIds: { '0': ObjectId('655b3244447bb9539187dcc89') },
    matchedCount: 0,
    modifiedCount: 0,
    deletedCount: 0,
   upsertedCount: 0,
   upsertedIds: {}
}
其中,document 是 insertOne 方法的第一个参数。

2) 使用bulkWrite方法更新数据

bulkWrite 方法支持更新单个文档和更新多个文档,语法格式如下:
// 更新文档
db.collection.bulkWrite([
    { updateOne/updateMany :
        {
            "filter": <document>,
            "update": <document or pipeline>, //4.2 及以上版本
            "upsert": <boolean>,
            "collation": <document>, // 3.4 及以上版本
            "arrayFilters": [ <filterdocument1>, ... ], // 3.6 及以上版本
            "hint": <document|string> // 4.2.1 及以上版本
        }
    }
])
以上方法涉及的参数与 db.collection.updateOne()、db.collection.updateMany() 方法的参数相同。参数描述如下:

3) 使用bulkWrite替换数据

使用 replaceOne 方法实现数据替换,语句如下:
db.collection.bulkWrite([
  { replaceOne :
    {
      "filter" : <document>,
      "replacement" : <document>,
      "upsert" : <boolean>,
      "collation": <document>,        // 3.4 及以上版本
      "hint": <document|string>       // 4.2.1 及以上版本
    }
  }
])

4) 使用bulkWrite删除数据

bulkWrite 支持删除单个文档和删除多个文档的操作,具体语法如下:
db.collection.bulkWrite([
    { deleteOne/deleteMany : {
        "filter" : <document>,
        "collation" : <document> // 3.4 及以上版本
    }}
])

5) 批量操作

如果在统一操作中,同时进行插入数据、更新数据、删除数据的操作,可以用如下形式:
db.collection.bulkWrite([
    {
        insertOne : <document>,
        updateOne : <document>,
        updateMany : <document>,
        replaceOne : <document>,
        deleteOne : <document>,
        deleteMany : <document>
    }
])
默认情况下,会从第一条语句按顺序向后依次执行。如果设置排序为否,即不按顺序执行,MongoDB 会根据性能自行将语句重新排序,最终执行结果与顺序执行有可能不同。

【实例】批量操作商品数据。把商品集合中出版社为“北京十月文艺出版社”的书,折扣价减3,然后给目前为 book 的文档增加字段“字数”,字段名为 words。在操作前先插入一些数据,数据内容为:
shopping> db.products.find()
[
  {
    "_id": ObjectId('65b3244a47bb9539187dcc89'),
    "name": "活着",
    "author": "余华",
    "press": "北京十月文艺出版社",
    "publishTime": "2021-10-01",
    "type": "book",
    "comments": "1332375",
    "price": 45,
    "discount": 31,
    "ebookPrice": 29
  },
  {
    "_id": ObjectId('65b34ec647bb9539187dcc8a'),
    "name": "人生",
    "author": "路遥",
    "press": "北京十月文艺出版社",
    "publishTime": "2021-07-01",
    "type": "book",
    "comments": "199187",
    "price": 39.5,
    "discount": 39.5,
    "ebookPrice": 27.2
  },
  {
    "_id": ObjectId('65b34fa347bb9539187dcc8b'),
    "name": "骆驼祥子",
    "author": "老舍",
    "press": "天津出版社",
    "publishTime:" "2020-10-01",
    "type": "book",
    "comments": "290320",
    "price": 30,
    "discount": 26,
    "ebookPrice": 25
  }
]

接下来执行批量操作语句,语句如下:
db.products.bulkWrite([
  {
    updateMany: { // 折扣价减 3
      "filter": { press: "北京十月文艺出版社" },
      "update": { $inc: { price: -3 } }
    }
  },
  {
    updateMany: { // 新增字数字段
      "filter": { type: "book" },
      "update": { $set: { words: '' } }
    }
  }
])
执行结果为:

{
  acknowledged: true,
  insertedCount: 0,
  insertedIds: {},
  matchedCount: 5,
  modifiedCount: 5,
  deletedCount: 0,
  upsetCount: 0,
  upsetIds: {}
}


然后再次查询上述数据,与操作之前对比,可以发现数据已被修改:
shopping> db.products.find()
[
  {
    "_id": ObjectId('65b3244a47bb9539187dcc89'),
    "name": "活着",
    "author": "余华",
    "press": "北京十月文艺出版社",
    "publishTime": "2021-10-01",
    "type": "book",
    "comments": "1332375",
    "price": 42,
    "discount": 31,
    "ebookPrice": 29,
    "words": ""
  },
  {
    "_id": ObjectId('65b34ec647bb9539187dcc8a'),
    "name": "人生",
    "author": "路遥",
    "press": "北京十月文艺出版社",
    "publishTime": "2021-07-01",
    "type": "book",
    "comments": "199187",
    "price": 36.5,
    "discount": 39.5,
    "ebookPrice": 27.2,
    "words": ""
  },
  {
    "_id": ObjectId('65b34fa347bb9539187dcc8b'),
    "name": "骆驼祥子",
    "author": "老舍",
    "press": "天津出版社",
    "publishTime": "2020-10-01",
    "type": "book",
    "comments": "290320",
    "price": 30,
    "discount": 26,
    "ebookPrice": 25,
    "words": ""
  }
]

相关文章