跳至主要內容

MongoDB 的 CRUD 操作

钝悟...大约 6 分钟数据库文档数据库MongoDB数据库文档数据库MongoDB

MongoDB 的 CRUD 操作

一、基本 CRUD 操作

MongoDB 的 CRUD 操作是针对 document 的读写操作。

Create 操作

MongoDB 提供以下操作向一个 collection 插入 document

注:以上操作都是原子操作。

img
img

插入操作的特性:

  • MongoDB 中的所有写操作都是单个文档级别的原子操作。
  • 如果要插入的 collection 当前不存在,则插入操作会自动创建 collection。
  • 在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的 _idopen in new window 字段作为主键。如果插入的文档省略 _id 字段,则 MongoDB 驱动程序会自动为 _id 字段生成 ObjectId。
  • 可以 MongoDB 写入操作的确认级别来控制写入行为。

【示例】插入一条 document 示例

db.inventory.insertOne({
  item: 'canvas',
  qty: 100,
  tags: ['cotton'],
  size: { h: 28, w: 35.5, uom: 'cm' }
})

【示例】插入多条 document 示例

db.inventory.insertMany([
  {
    item: 'journal',
    qty: 25,
    tags: ['blank', 'red'],
    size: { h: 14, w: 21, uom: 'cm' }
  },
  {
    item: 'mat',
    qty: 85,
    tags: ['gray'],
    size: { h: 27.9, w: 35.5, uom: 'cm' }
  },
  {
    item: 'mousepad',
    qty: 25,
    tags: ['gel', 'blue'],
    size: { h: 19, w: 22.85, uom: 'cm' }
  }
])

Read 操作

MongoDB 提供 db.collection.find()open in new window 方法来检索 document。

img
img

Update 操作

MongoDB 提供以下操作来更新 collection 中的 document

语法格式:

img
img

【示例】插入测试数据

db.inventory.insertMany([
  {
    item: 'canvas',
    qty: 100,
    size: { h: 28, w: 35.5, uom: 'cm' },
    status: 'A'
  },
  { item: 'journal', qty: 25, size: { h: 14, w: 21, uom: 'cm' }, status: 'A' },
  { item: 'mat', qty: 85, size: { h: 27.9, w: 35.5, uom: 'cm' }, status: 'A' },
  {
    item: 'mousepad',
    qty: 25,
    size: { h: 19, w: 22.85, uom: 'cm' },
    status: 'P'
  },
  {
    item: 'notebook',
    qty: 50,
    size: { h: 8.5, w: 11, uom: 'in' },
    status: 'P'
  },
  { item: 'paper', qty: 100, size: { h: 8.5, w: 11, uom: 'in' }, status: 'D' },
  {
    item: 'planner',
    qty: 75,
    size: { h: 22.85, w: 30, uom: 'cm' },
    status: 'D'
  },
  {
    item: 'postcard',
    qty: 45,
    size: { h: 10, w: 15.25, uom: 'cm' },
    status: 'A'
  },
  {
    item: 'sketchbook',
    qty: 80,
    size: { h: 14, w: 21, uom: 'cm' },
    status: 'A'
  },
  {
    item: 'sketch pad',
    qty: 95,
    size: { h: 22.85, w: 30.5, uom: 'cm' },
    status: 'A'
  }
])

【示例】更新一条 document

db.inventory.updateOne(
  { item: 'paper' },
  {
    $set: { 'size.uom': 'cm', status: 'P' },
    $currentDate: { lastModified: true }
  }
)

【示例】更新多条 document

db.inventory.updateMany(
  { qty: { $lt: 50 } },
  {
    $set: { 'size.uom': 'in', status: 'P' },
    $currentDate: { lastModified: true }
  }
)

【示例】替换一条 document

db.inventory.replaceOne(
  { item: 'paper' },
  {
    item: 'paper',
    instock: [
      { warehouse: 'A', qty: 60 },
      { warehouse: 'B', qty: 40 }
    ]
  }
)

更新操作的特性:

  • MongoDB 中的所有写操作都是单个文档级别的原子操作。
  • 一旦设置了,就无法更新或替换 _idopen in new window 字段。
  • 除以下情况外,MongoDB 会在执行写操作后保留文档字段的顺序:
    • _id 字段始终是文档中的第一个字段。
    • 包括重命名字段名称的更新可能导致文档中字段的重新排序。
  • 如果更新操作中包含 upsert : true 并且没有 document 匹配过滤器,MongoDB 会新插入一个 document;如果有匹配的 document,MongoDB 会修改或替换这些 document。

Delete 操作

MongoDB 提供以下操作来删除 collection 中的 document

img
img

删除操作的特性:

  • MongoDB 中的所有写操作都是单个文档级别的原子操作。

二、批量写操作

MongoDB 通过 db.collection.bulkWrite()open in new window 方法来支持批量写操作(包括批量插入、更新、删除)。

此外,db.collection.insertMany()open in new window 方法支持批量插入操作。

有序和无序的操作

批量写操作可以有序或无序。

  • 对于有序列表,MongoDB 串行执行操作。如果在写操作的处理过程中发生错误,MongoDB 将不处理列表中剩余的写操作。
  • 对于无序列表,MongoDB 可以并行执行操作,但是不能保证此行为。如果在写操作的处理过程中发生错误,MongoDB 将继续处理列表中剩余的写操作。

在分片集合上执行操作的有序列表通常比执行无序列表要慢,因为对于有序列表,每个操作必须等待上一个操作完成。

默认情况下,bulkWrite()open in new window 执行有序操作。要指定无序写操作,请在选项文档中设置 ordered : false

bulkWrite() 方法

bulkWrite()open in new window 支持以下写操作:

【示例】批量写操作示例

try {
  db.characters.bulkWrite([
    {
      insertOne: {
        document: {
          _id: 4,
          char: 'Dithras',
          class: 'barbarian',
          lvl: 4
        }
      }
    },
    {
      insertOne: {
        document: {
          _id: 5,
          char: 'Taeln',
          class: 'fighter',
          lvl: 3
        }
      }
    },
    {
      updateOne: {
        filter: { char: 'Eldon' },
        update: { $set: { status: 'Critical Injury' } }
      }
    },
    { deleteOne: { filter: { char: 'Brisbane' } } },
    {
      replaceOne: {
        filter: { char: 'Meldane' },
        replacement: { char: 'Tanys', class: 'oracle', lvl: 4 }
      }
    }
  ])
} catch (e) {
  print(e)
}

批量写操作策略

大量的插入操作(包括初始数据插入或常规数据导入)可能会影响分片集群的性能。对于批量插入,请考虑以下策略:

预拆分 collection

如果分片集合为空,则该集合只有一个初始 chunkopen in new window,该 chunkopen in new window 位于单个分片上。然后,MongoDB 必须花一些时间来接收数据,创建拆分并将拆分的块分发到可用的分片。为了避免这种性能成本,您可以按照拆分群集中的拆分块中的说明预拆分 collection。

无序写操作

要提高对分片集群的写入性能,请使用 bulkWrite()open in new window,并将可选参数顺序设置为 false。mongosopen in new window 可以尝试同时将写入操作发送到多个分片。对于空集合,首先按照分片群集中的分割 chunkopen in new window 中的说明预拆分 collection。

避免单调节流

如果在一次插入操作中,分片 key 单调递增,那么所有的插入数据都会存入 collection 的最后一个 chunk,也就是存入一个分片中。因此,集群的插入容量将永远不会超过该单个分片的插入容量。

如果插入量大于单个分片可以处理的插入量,并且无法避免单调递增的分片键,那么请考虑对应用程序进行以下修改:

  • 反转分片密钥的二进制位。这样可以保留信息,并避免将插入顺序与值序列的增加关联起来。
  • 交换第一个和最后一个 16 位字以“随机”插入。

SQL 和 MongoDB 对比

术语和概念

SQL 术语和概念MongoDB 术语和概念
databasedatabaseopen in new window
tablecollectionopen in new window
rowdocumentopen in new windowBSONopen in new window
columnfieldopen in new window
indexindexopen in new window
table joins$lookupopen in new window、嵌入式文档
primary keyprimary keyopen in new window
MongoDB 中自动设置主键为 _idopen in new window 字段
aggregation (e.g. group by)aggregation pipeline
参考 SQL to Aggregation Mapping Chartopen in new window.
SELECT INTO NEW_TABLE$outopen in new window
参考 SQL to Aggregation Mapping Chartopen in new window
MERGE INTO TABLE$mergeopen in new window (MongoDB 4.2 开始支持)
参考 SQL to Aggregation Mapping Chartopen in new window.
UNION ALL$unionWithopen in new window (MongoDB 4.4 开始支持)
transactionstransactionsopen in new window

参考资料

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.7