MongoDB快速实战与基本原理

news2024/10/6 14:33:59

MongoDB 介绍

什么是 MongoDB

MongoDB 是一个文档数据库(以 JSON 为数据模型),由 C++ 语言编写,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
文档来自于“JSON Document”,并非我们一般理解的 PDF、WORD 文档。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,数据格式是 BSON,一种类似 JSON 的二进制形式的存储格式,简称 Binary JSON,和 JSON 一样支持内嵌的文档对象和数组对象,因此可以存储比较复杂的数据类型。Mongo 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。原则上 Oracle 和 MySQL 能做的事情,MongoDB 都能做(包括 ACID 事务)。
MongoDB 在数据库总排名第 5,仅次于 Oracle、MySQL 等 RDBMS,在 NoSQL 数据库排名首位。从诞生以来,其项目应用广度、社区活跃指数持续上升。

数据库排名网站:https://db-engines.com/en/ranking

image.png

MongoDB6.0 新特性

该版本的主要功能特性包括:

  • 时序集合增强
  • Change Stream 增强
  • 可查询加密
  • 聚合&query 能力增强
  • 集群同步

官网关于升级到 MongoDB6.0 的原因:https://www.mongodb.com/blog/post/big-reasons-upgrade-mongodb-6-0
官方文档:https://www.mongodb.com/docs/v6.0/
MongoDB6.0 发行版本说明:https://www.mongodb.com/docs/v6.0/release-notes/6.0/
阿里云关于 MongoDB6.0 新特性说明:https://help.aliyun.com/document_detail/462614.html?spm=a2c4g.312011.0.0.75b42ab8s9NasS#section-hvy-d22-stk

MongoDB vs 关系型数据库

MongoDB 概念与关系型数据库(RDBMS)非常类似:

SQL 概念MongoDB 概念
数据库(database)数据库(database)
表(table)集合(collection)
行(row)文档(document)
列(column)字段(field)
索引(index)索引(index)
主键(primary key)_id(字段)
视图(view)视图(view)
表连接(table joins)聚合操作($lookup)
  • 数据库(database):最外层的概念,可以理解为逻辑上的名称空间,一个数据库包含多个不同名称的集合。
  • 集合(collection):相当于SQL中的表,一个集合可以存放多个不同的文档。
  • 文档(document):一个文档相当于数据表中的一行,由多个不同的字段组成。
  • 字段(field):文档中的一个属性,等同于列(column)。
  • 索引(index):独立的检索式数据结构,与 SQL 概念一致。
  • _id:每个文档中都拥有一个唯一的 _id 字段,相当于 SQL 中的主键(primary key)。
  • 视图(view):可以看作一种虚拟的(非真实存在的)集合,与 SQL 中的视图类似。从 MongoDB3.4 版本开始提供了视图功能,其通过聚合管道技术实现。
  • 聚合操作($lookup):MongoDB 用于实现“类似”表连接(tablejoin)的聚合操作符。

尽管这些概念大多与 SQL 标准定义类似,但 MongoDB 与传统 RDBMS 仍然存在不少差异,包括:

  • 半结构化

在一个集合中,文档所拥有的字段并不需要是相同的,而且也不需要对所用的字段进行声明。因此,MongoDB 具有很明显的半结构化特点。除了松散的表结构,文档还可以支持多级的嵌套、数组等灵活的数据类型,非常契合面向对象的编程模型。

  • 弱关系

MongoDB 没有外键的约束,也没有非常强大的表连接能力。类似的功能需要使用聚合管道技术来弥补。

MongoDB 技术优势

MongoDB 基于灵活的 JSON 文档模型,非常适合敏捷式的快速开发。与此同时,其与生俱来的高可用、高水平扩展能力使得它在处理海量、高并发的数据应用时颇具优势。

  • JSON 结构和对象模型接近,开发代码量低
  • JSON 的动态模型意味着更容易响应新的业务需求
  • 复制集提供 99.999% 高可用
  • 分片架构支持海量数据和无缝扩容

MongoDB 与关系型数据库对比:


MongoDB关系型数据库
亿级以上数据量轻松支持分库分表
灵活表结构轻松支持Entity Key/Value 表,关联查询比较痛苦
高并发读轻松支持需要优化
高并发写轻松支持需要优化
跨地区集群轻松支持需要定制方案
分片集群轻松支持需要中间件
地理位置查询比较完整的地理位置PG 还可以,其他数据库略麻烦
聚合计算功能很强大使用 Group By 等,能力有限
异构数据轻松支持使用 EKV 属性表
大宽表轻松支持性能受限

MongoDB 应用场景

从目前阿里云 MongoDB 云数据库上的用户看,MongoDB 的应用已经渗透到各个领域:

  • 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新;
  • 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来;
  • 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能;
  • 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析;
  • 视频直播,使用 MongoDB 存储用户信息、礼物信息等;
  • 大数据应用,使用云数据库 MongoDB 作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。

当前业务是否适合使用 MongoDB?

没有某个业务场景必须要使用 MongoDB 才能解决,但使用 MongoDB 通常能让你以更低的成本解决问题。如果你不清楚当前业务是否适合使用 MongoDB,可以通过做几道选择题来辅助决策。

应用特征Yes/No
应用不需要复杂/长事务及 join 支持必须 Yes
新应用,需求会变,数据模型无法确定,想快速迭代开发?
应用需要 2000-3000 以上的读写 QPS(更高也可以)?
应用需要 TB 甚至 PB 级别数据存储?
应用发展迅速,需要能快速水平扩展?
应用要求存储的数据不丢失?
应用需要 99.999% 高可用?
应用需要大量的地理位置查询、文本查询?

只要有一项需求满足就可以考虑使用 MongoDB,匹配越多,选择 MongoDB 越合适。

MongoDB 环境搭建

linux 安装 MongoDB

1)环境准备

linux系统:centos7
安装 MongoDB 社区版

# 查看linux版本
[root@hecs-403280 ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

2)下载 MongoDB Community Server

下载地址:https://www.mongodb.com/try/download/community

image.png

# 下载MongoDB
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-6.0.5.tgz
tar -zxvf mongodb-linux-x86_64-rhel70-6.0.5.tgz

3)启动 MongoDB Server

# 创建dbpath和logpath
[root@hecs-403280 mongodb]# pwd
/usr/local/mongodb
[root@hecs-403280 mongodb]# mkdir -p data log
[root@hecs-403280 mongodb]# ls
bin  data  LICENSE-Community.txt  log  MPL-2  README  THIRD-PARTY-NOTICES

# 进入mongodb目录,启动mongodb服务
bin/mongod --port=27017 --dbpath=/usr/local/mongodb/data --logpath=/usr/local/mongodb/log/mongodb.log --bind_ip=0.0.0.0 --fork

–dbpath:指定数据文件存放目录
–logpath:指定日志文件,注意是指定文件不是目录
–logappend:使用追加的方式记录日志
–port:指定端口,默认为27017
–bind_ip:默认只监听localhost网卡
–fork:后台启动
–auth:开启认证模式

image.png

4)添加环境变量
修改/etc/profile,添加环境变量,方便执行 MongoDB 命令

export MONGODB_HOME=/usr/local/mongodb
PATH=$PATH:$MONGODB_HOME/bin   

然后执行 source /etc/profile 重新加载环境变量。

5)利用配置文件启动服务
编辑/usr/local/mongodb/conf/mongo.conf文件,内容如下:

systemLog:
  destination: file
  path: /usr/local/mongodb/log/mongod.log # log path
  logAppend: true
storage:
  dbPath: /usr/local/mongodb/data # data directory
  engine: wiredTiger  #存储引擎
  journal:            #是否启用journal日志
    enabled: true
net:
  bindIp: 0.0.0.0
  port: 27017 # port
processManagement:
  fork: true

注意:一定要yaml格式。
启动 mongod:

mongod -f /usr/local/mongodb/conf/mongo.conf

-f 选项表示将使用配置文件启动 mongodb。

6)关闭 MongoDB 服务
方式 1:

mongod --port=27017 --dbpath=/usr/local/mongodb/data --shutdown

方式 2:
进入 mongosh

use admin
# 关闭 MongoDB server 服务
db.shutdownServer()

mongosh 使用

mongosh 是 MongoDB 的交互式 JavaScript Shell 界面,它为系统管理员提供了强大的界面,并为开发人员提供了直接测试数据库查询和操作的方法。
注意:MongoDB 6.0 移除了mongo,使用 mongosh。

mongosh 下载地址:https://www.mongodb.com/try/download/shell

# centos7 安装mongosh
wget https://downloads.mongodb.com/compass/mongodb-mongosh-1.8.0.x86_64.rpm
yum install -y mongodb-mongosh-1.8.0.x86_64.rpm
# 连接mongodb server端
# mongosh --host=192.168.65.206 --port=27017 
# mongosh 192.168.65.206:27017
# 指定uri方式连接
# mongosh mongodb://192.168.65.206:27017/test
mongosh

–port:指定端口,默认为27017
–host:连接的主机地址,默认127.0.0.1

image.png

mongosh 常用命令

命令说明
show dbs | show databases显示数据库列表
use 数据库名切换数据库,如果不存在创建数据库
db.dropDatabase()删除数据库
show collections | show tables显示当前数据库的集合列表
db.集合名.stats()查看集合详情
db.集合名.drop()删除集合
show users显示当前数据库的用户列表
show roles显示当前数据库的角色列表
show profile显示最近发生的操作
load(“xxx.js”)执行一个 JavaScript 脚本文件
exit | quit退出当前 shell
help查看 mongodb 支持哪些命令
db.help()查询当前数据库支持的方法
db.集合名.help()显示集合的帮助信息
db.version()查看数据库版本

数据库操作

# 查看所有库
show dbs
# 切换到指定数据库,不存在则创建
use test
# 删除当前数据库  
db.dropDatabase()

集合操作

# 查看集合
show collections
# 创建集合
db.createCollection("emp")
# 删除集合
db.emp.drop()

创建集合语法

db.createCollection(name, options)

options 参数:

字段类型描述
capped布尔(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。
size数值(可选)为固定集合指定一个最大值(以字节计)。
如果 capped 为 true,也需要指定该字段。
max数值(可选)指定固定集合中包含文档的最大数量。

注意:当集合不存在时,向集合中插入文档也会创建集合。

安全认证

使用用户名和密码来认证用户身份是 MongoDB 中最常用的安全认证方式。可以通过以下步骤实现:

  • 创建一个管理员用户(root)并设置密码,具有所有数据库的管理权限。
  • 创建一个或多个普通用户,指定相应的数据库和集合权限,并设置密码。

启用认证后,客户端连接 MongoDB 服务器时需要提供用户名和密码才能成功连接。

创建管理员用户

# 设置管理员用户名密码需要切换到admin库
use admin  
# 创建管理员
db.createUser({user:"firechou",pwd:"firechou",roles:["root"]})
# 查看当前数据库所有用户信息 
show users 
# 显示可设置权限
show roles 
# 显示所有用户
db.system.users.find()

image.png

常用权限

权限名描述
read允许用户读取指定数据库
readWrite允许用户读写指定数据库
dbAdmin允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问 system.profile
dbOwner允许用户在指定数据库中执行任意操作,增、删、改、查等
userAdmin允许用户向 system.users 集合写入,可以在指定数据库里创建、删除和管理用户
clusterAdmin只在 admin 数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
readAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的 userAdmin 权限
dbAdminAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的 dbAdmin 权限
root只在 admin 数据库中可用。超级账号,超级权限

重新赋予用户操作权限:

db.grantRolesToUser( "firechou" , [ 
    { role: "clusterAdmin", db: "admin" } ,
     { role: "userAdminAnyDatabase", db: "admin"},
     { role: "readWriteAnyDatabase", db: "admin"} 
 ])

删除用户:

db.dropUser("firechou")
# 删除当前数据库所有用户
db.dropAllUser()

用户认证,返回 1 表示认证成功:
image.png

创建应用数据库用户

use appdb
db.createUser({user:"appdb",pwd:"firechou",roles:["dbOwner"]})

MongoDB 启用鉴权

默认情况下,MongoDB 不会启用鉴权,以鉴权模式启动 MongoDB:

mongod -f /usr/local/mongodb/conf/mongo.conf --auth

启用鉴权之后,连接 MongoDB 的相关操作都需要提供身份认证。

mongosh 192.168.65.206:27017 -u firechou -p firechou --authenticationDatabase=admin

Docker 安装 MongoDB

https://hub.docker.com/_/mongo?tab=description&page=3

# 拉取mongo镜像
docker pull mongo:6.0.5
# 运行mongo镜像
docker run --name mongo-server -p 29017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=firechou \
-e MONGO_INITDB_ROOT_PASSWORD=firechou \
-d mongo:6.0.5 --wiredTigerCacheSizeGB 1

默认情况下,Mongo 会将 wiredTigerCacheSizeGB 设置为与主机总内存成比例的值,而不考虑你可能对容器施加的内存限制。
MONGO_INITDB_ROOT_USERNAME 和 MONGO_INITDB_ROOT_PASSWORD 都存在就会启用身份认证(mongod --auth)
利用 mongosh 建立连接:

# 远程连接
mongosh ip:29017 -u firechou -p firechou

MongoDB 常用工具

GUI 工具

(1)官方GUI:COMPASS
MongoDB 图形化管理工具(GUI),能够帮助您在不需要知道 MongoDB 查询语法的前提下,便利地分析和理解您的数据库模式,并且帮助您可视化地构建查询。

下载地址:https://www.mongodb.com/zh-cn/products/compass

image.png

(2)Robo 3T(免费)

下载地址:https://robomongo.org/

(3)Studio 3T(收费,试用30天)

下载地址:https://studio3t.com/download/

MongoDB Database Tools

下载地址:https://www.mongodb.com/try/download/database-tools

文件名称作用
mongostat数据库性能监控工具
mongotop热点表监控工具
mongodump数据库逻辑备份工具
mongorestore数据库逻辑恢复工具
mongoexport数据导出工具
mongoimport数据导入工具
bsondumpBSON 格式转换工具
mongofilesGridFS 文件工具

MongoDB 文档操作

SQL to MongoDB Mapping Chart :https://www.mongodb.com/docs/manual/reference/sql-comparison/

插入文档

MongoDB 提供了以下方法将文档插入到集合中:

  • db.collection.insertOne ():将单个文档插入到集合中。
  • db.collection.insertMany ():将多个文档插入到集合中。

新增单个文档

  • insertOne:用于向集合中插入一条文档数据,支持 writeConcern。语法如下:
db.collection.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)

image.png
设置 writeConcern 参数的示例:

db.emps.insertOne(
   { name: "firechou", age: 33},
   {
      writeConcern: { w: "majority", j: true, wtimeout: 5000 }
   }
)

image.png
writeConcern 是 MongoDB 中用来控制写入确认的选项。以下是 writeConcern 参数的一些常见选项:

w:指定写入确认级别。如果指定为数字,则表示要等待写入操作完成的节点数。如果指定为 majority,则表示等待大多数节点完成写入操作。默认为 1,表示等待写入操作完成的节点数为 1。
j:表示写入操作是否要求持久化到磁盘。如果设置为 true,则表示写入操作必须持久化到磁盘后才返回成功。如果设置为 false,则表示写入操作可能在数据被持久化到磁盘之前返回成功。默认为 false。
wtimeout:表示等待写入操作完成的超时时间,单位为毫秒。如果超过指定的时间仍然没有返回确认信息,则返回错误。默认为 0,表示不设置超时时间。

批量新增文档

  • insertMany:向指定集合中插入多条文档数据
db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>      
   }
)

writeConcern:写入确认选项,可选。
ordered:指定是否按顺序写入,默认 true,按顺序写入。

db.emps.insertMany([{x:1},{y:5}])

image.png

测试:批量插入 50 条随机数据
编辑脚本 book.js:

var tags = ["nosql","mongodb","document","developer","popular"];
var types = ["technology","sociality","travel","novel","literature"];
var books=[];
for(var i=0;i<50;i++){
    var typeIdx = Math.floor(Math.random()*types.length);
    var tagIdx = Math.floor(Math.random()*tags.length);
    var favCount = Math.floor(Math.random()*100);
    var book = {
        title: "book-"+i,
        type: types[typeIdx],
        tag: tags[tagIdx],
        favCount: favCount,
        author: "xxx"+i
    };
    books.push(book)
}
db.books.insertMany(books);

进入 mongosh,执行:

load("books.js")

image.png

查询文档

查询集合中的若干文档
语法格式如下:

db.collection.find(query, projection)

query:可选,使用查询操作符指定查询条件
projection:可选,使用投影操作符指定返回的键。查询时返回文档中所有键值,只需省略该参数即可(默认省略)。投影时,_id 为 1 的时候,其他字段必须是 1;_id 是 0 的时候,其他字段可以是 0;如果没有 _id 字段约束,多个其他字段必须同为 0 或同为 1。

如果查询返回的条目数量较多,mongosh 则会自动实现分批显示。默认情况下每次只显示 20 条,可以输入 it 命令读取下一批。
image.png

查询集合中的第一个文档

语法格式如下:

db.collection.findOne(query, projection)

示例:

db.books.findOne()
db.books.find({tag:"nosql"},{title:1,author:1})

image.png
如果你需要以易读的方式来读取数据,可以使用 pretty 方法,语法格式如下:

db.collection.find().pretty()

注意:pretty() 方法以格式化的方式来显示所有文档。

条件查询

查询条件对照表:

**SQL **MQL
a = 1{a: 1}
a <> 1{a: {$ne: 1}}
a > 1{a: {$gt: 1}}
a >= 1{a: {$gte: 1}}
a < 1{a: {$lt: 1}}
a <= 1{a: {$lte: 1}}

查询逻辑对照表:

**SQL **MQL
a = 1 AND b = 1{a: 1, b: 1}或{$and: [{a: 1}, {b: 1}]}
a = 1 OR b = 1{$or: [{a: 1}, {b: 1}]}
a IS NULL{a: {$exists: false}}
a IN (1, 2, 3){a: {$in: [1, 2, 3]}}

查询逻辑运算符:

$lt: 存在并小于
$lte: 存在并小于等于
$gt: 存在并大于
$gte: 存在并大于等于
$ne: 不存在或存在但不等于
$in: 存在并在指定数组中
$nin: 不存在或不在指定数组中
$or: 匹配两个或多个条件中的一个
$and: 匹配全部条件

# 查询带有nosql标签的book文档:
db.books.find({tag:"nosql"})
# 按照id查询单个book文档:
db.books.find({_id:ObjectId("6596c598e226cbe365ee4796")})
# 查询分类为“travel”、收藏数超过60个的book文档:
db.books.find({type:"travel",favCount:{$gt:60}})

正则表达式匹配查询

MongoDB 使用 $regex 操作符来设置匹配字符串的正则表达式。

# 使用正则表达式查找type包含 so 字符串的book
db.books.find({type:{$regex:"so"}})
# 或者
db.books.find({type:/so/})

排序

在 MongoDB 中使用 sort() 方法对数据进行排序

# 指定按收藏数(favCount)降序返回
db.books.find({type:"travel"}).sort({favCount:-1})

1 为升序排列,而 -1 是用于降序排列

image.png

分页

skip 用于指定跳过记录数,limit 则用于限定返回结果数量。可以在执行 find 命令的同时指定 skip、limit 参数,以此实现分页的功能。
比如,假定每页大小为 8 条,查询第 3 页的 book 文档:

db.books.find().skip(16).limit(8)

.skip(16) 表示跳过前面 16 条记录,即前两页的所有记录。
.limit(8) 表示返回 8 条记录,即第三页的所有记录。

(1)处理分页问题-巧分页
数据量大的时候,应该避免使用 skip/limit 形式的分页。
替代方案:使用查询条件+唯一排序条件。
例如:

# 第一页
db.books.find({}).sort({_id: 1}).limit(10); 
# 第二页
db.books.find({_id: {$gt: <第一页最后一个_id>}}).sort({_id: 1}).limit(10); 
# 第三页
db.books.find({_id: {$gt: <第二页最后一个_id>}}).sort({_id: 1}).limit(10);

(2)处理分页问题–避免使用 count
尽可能不要计算总页数,特别是数据量大和查询条件不能完整命中索引时。
考虑以下场景:假设集合总共有 1000w 条数据,在没有索引的情况下考虑以下查询:

db.coll.find({x: 100}).limit(50);
db.coll.count({x: 100}); 

前者只需要遍历前 n 条,直到找到 50 条 x=100 的文档即可结束;
后者需要遍历完 1000w 条找到所有符合要求的文档才能得到结果。为了计算总页数而进行的 count() 往往是拖慢页面整体加载速度的原因;

更新文档

MongoDB 提供了以下方法来更新集合中的文档:

  • db.collection.updateOne ()

即使多个文档可能与指定的筛选器匹配,也只会更新第一个匹配的文档。

  • db.collection.updateMany ()

更新与指定筛选器匹配的所有文档。

更新操作符:

操作符格式描述
$set{$set:{field:value}}指定一个键并更新值,若键不存在则创建
$unset{$unset : {field : 1 }}删除一个键
$inc{$inc : {field : value } }对数值类型进行增减
$rename{$rename : {old_field_name : new_field_name } }修改字段名称
$push{ $push : {field : value } }将数值追加到数组中,若数组不存在则会进行初始化
$pushAll{$pushAll : {field : value_array }}追加多个值到一个数组字段内
$pull{$pull : {field : _value } }从数组中删除指定的元素
$addToSet{$addToSet : {field : value } }添加元素到数组中,具有排重功能
$pop{$pop : {field : 1 }}删除数组的第一个或最后一个元素

更新单个文档

updateOne 语法如下:

db.collection.updateOne(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }
)

db.collection.updateOne() 方法的参数含义如下:

:一个筛选器对象,用于指定要更新的文档。只有与筛选器对象匹配的第一个文档才会被更新。
:一个更新操作对象,用于指定如何更新文档。可以使用一些操作符,例如 s e t 、 set、 setinc、 u n s e t 等,以更新文档中的特定字段。 u p s e r t :一个布尔值,用于指定如果找不到与筛选器匹配的文档时是否应插入一个新文档。如果 u p s e r t 为 t r u e ,则会插入一个新文档。默认值为 f a l s e 。 w r i t e C o n c e r n :一个文档,用于指定写入操作的安全级别。可以指定写入操作需要到达的节点数或等待写入操作的时间。 c o l l a t i o n :一个文档,用于指定用于查询的排序规则。例如,可以通过指定 l o c a l e 属性来指定语言环境,从而实现基于区域设置的排序。 a r r a y F i l t e r s :一个数组,用于指定要更新的数组元素。数组元素是通过使用更新操作符 unset 等,以更新文档中的特定字段。 upsert:一个布尔值,用于指定如果找不到与筛选器匹配的文档时是否应插入一个新文档。如果 upsert 为 true,则会插入一个新文档。默认值为 false。 writeConcern:一个文档,用于指定写入操作的安全级别。可以指定写入操作需要到达的节点数或等待写入操作的时间。 collation:一个文档,用于指定用于查询的排序规则。例如,可以通过指定 locale 属性来指定语言环境,从而实现基于区域设置的排序。 arrayFilters:一个数组,用于指定要更新的数组元素。数组元素是通过使用更新操作符 unset等,以更新文档中的特定字段。upsert:一个布尔值,用于指定如果找不到与筛选器匹配的文档时是否应插入一个新文档。如果upserttrue,则会插入一个新文档。默认值为falsewriteConcern:一个文档,用于指定写入操作的安全级别。可以指定写入操作需要到达的节点数或等待写入操作的时间。collation:一个文档,用于指定用于查询的排序规则。例如,可以通过指定locale属性来指定语言环境,从而实现基于区域设置的排序。arrayFilters:一个数组,用于指定要更新的数组元素。数组元素是通过使用更新操作符[]和$来指定的。
hint:一个文档或字符串,用于指定查询使用的索引。该参数仅在 MongoDB 4.2.1 及以上版本中可用。
注意,除了 filter 和 update 参数外,其他参数都是可选的。

某个 book 文档被收藏了,则需要将该文档的 favCount 字段自增:

db.books.updateOne({_id:ObjectId("6596c598e226cbe365ee47ac")},{$inc:{favCount:1}})

image.png
upsert 是一种特殊的更新,其表现为如果目标文档不存在,则执行插入命令。

db.books.updateOne(
    {title:"my book"},
    {$set:{tags:["nosql","mongodb"],type:"none",author:"firechou"}},
    {upsert:true}
)

更新多个文档

updateMany 更新与集合的指定筛选器匹配的所有文档.
将分类为“novel”的文档的增加发布时间(publishedDate):

db.books.updateMany({type:"novel"},{$set:{publishedDate:new Date()}})

(1)findAndModify
findAndModify 兼容了查询和修改指定文档的功能,findAndModify 只能更新单个文档:

# 将某个book文档的收藏数(favCount)加1
db.books.findAndModify({
    query:{_id:ObjectId("6457a39c817728350ec83b9d")},
    update:{$inc:{favCount:1}}
})

该操作会返回符合查询条件的文档数据,并完成对文档的修改。
默认情况下,findAndModify 会返回修改前的“旧”数据。如果希望返回修改后的数据,则可以指定 new 选项:

db.books.findAndModify({
    query:{_id:ObjectId("6457a39c817728350ec83b9d")},
    update:{$inc:{favCount:1}},
    new: true
})

与 findAndModify 语义相近的命令如下:

  • findOneAndUpdate:更新单个文档并返回更新前(或更新后)的文档。
  • findOneAndReplace:替换单个文档并返回替换前(或替换后)的文档。

删除文档

deleteOne & deleteMany

官方推荐使用 deleteOne() 和 deleteMany() 方法删除文档,语法格式如下:

# 删除 type 等于 novel 的一个文档
db.books.deleteOne({ type:"novel" })
# 删除集合下全部文档
db.books.deleteMany({})
# 删除 type等于 novel 的全部文档
db.books.deleteMany({ type:"novel" })

注意:remove、deleteMany 命令需要对查询范围内的文档逐个删除,如果希望删除整个集合,则使用 drop 命令会更加高效。

findOneAndDelete

deleteOne 命令在删除文档后只会返回确认性的信息,如果希望获得被删除的文档,则可以使用 findOneAndDelete 命令:

db.books.findOneAndDelete({type:"novel"})

除了在结果中返回删除文档,findOneAndDelete 命令还允许定义“删除的顺序”,即按照指定顺序删除找到的第一个文档。利用这个特性,findOneAndDelete 可以实现队列的先进先出:

db.books.findOneAndDelete({type:"novel"},{sort:{favCount:1}})

批量操作

bulkwrite() 方法提供了执行批量插入、更新和删除操作的能力。
bulkWrite() 支持以下写操作:

  • insertOne
  • updateOne
  • updateMany
  • replaceOne
  • deleteOne
  • deleteMany

每个写操作都作为数组中的文档传递给 bulkWrite()。

db.pizzas.insertMany( [
   { _id: 0, type: "pepperoni", size: "small", price: 4 },
   { _id: 1, type: "cheese", size: "medium", price: 7 },
   { _id: 2, type: "vegan", size: "large", price: 8 }
] )

db.pizzas.bulkWrite( [
      { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } },
      { insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } },
      { updateOne: {
         filter: { type: "cheese" },
         update: { $set: { price: 8 } }
      } },
      { deleteOne: { filter: { type: "pepperoni"} } },
      { replaceOne: {
         filter: { type: "vegan" },
         replacement: { type: "tofu", size: "small", price: 4 }
      } }
   ] )

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1357325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【K8S 云原生】Pod资源限制、Pod容器健康检查(探针)

目录 一、docker的重启方式和K8S重启方式 1、Pod的重启方式&#xff1a; 2、docker的重启策略&#xff1a; 二、yaml文件快速生成&#xff1a; 三、pod的状态&#xff1a; 四、Pod的资源限制 1、限制的方式和种类 2、CPU的限制的格式&#xff1a; 五、K8S拉取镜像的策…

电源板设计方案怎么写 (评审文件)

1. 首先是大致的图形模块化说明。 1. 大致的框图 2. 统计项目需要的功率和需求 此表格数据是假的&#xff0c;只是为了展示 电源种类是&#xff1a; 板子需要供电需要的电压和对应电压最大的电流。 电源时序是&#xff1a; 板子…

智能穿戴时代 | 米客方德SD NAND的崭新优势

SD NAND在智能穿戴上的优势 SD NAND是一种可以直接焊接在智能穿戴设备主板上的存储芯片&#xff0c;其小型化设计有助于紧凑设备尺寸&#xff0c;同时提供可靠的嵌入式存储解决方案。 这种集成设计减少了空间占用&#xff0c;同时确保设备在高度活动的环境中更为稳定。SD NAND…

【C#】知识点实践序列之UrlEncode在线URL网址编码、解码

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是2024年第8篇文章&#xff0c;此篇文章是C#知识点实践序列文章&#xff0c; 博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 地址编码大家应该比较经常遇到和使用到&…

rk3566 armbian修复usb2.0并挂载U盘

文章目录 usb接口修复一 执行命令二 修改rk3566-panther-x2.dts⽂件三 查看是否识别 U盘格式化、挂载一 U盘格式化1.1 查看U盘1.2 查看U盘文件系统类型1.3 格式化为ext4系统 二 挂载U盘2.1 手动挂载2.2 自动挂载&#xff08;可选&#xff09; usb接口修复 一 执行命令 将位于…

【数据库系统概论】数据库恢复机制

系统文章目录 数据库的四个基本概念&#xff1a;数据、数据库、数据库管理系统和数据库系统 数据库系统的三级模式和二级映射 数据库系统外部的体系结构 数据模型 关系数据库中的关系操作 SQL是什么&#xff1f;它有什么特点&#xff1f; 数据定义之基本表的定义/创建、修改和…

泽攸科技完全自主研制的电子束光刻机取得阶段性成果

国产电子束光刻机实现自主可控&#xff0c;是实现我国集成电路产业链自主可控的重要一环。近日&#xff0c;泽攸科技联合松山湖材料实验室开展的全自主电子束光刻机整机的开发与产业化项目取得重大进展&#xff0c;成功研制出电子束光刻系统&#xff0c;实现了电子束光刻机整机…

FreeRTOS——互斥信号量知识总结及其实战

1互斥信号量的概念 1&#xff09;互斥信号量&#xff1a;是一个拥有优先级继承的二值信号量&#xff0c;在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中&#xff01; 2&#xff09;优先级继承&#xff1a;当一个互斥信号量正在被一个低优先级的…

MySQL 8.0 开关 Redo Logging

一 前言 前几天有客户测试使用云数据库的时候提出 要禁止mydumper 关闭redo log的操作 (说白了就是导入数据时保持MySQL 实例的redo logging功能)&#xff0c; 这才想起 在 MySQL 8.0.21 版本中&#xff0c;开启了一个新特性 “Redo Logging 动态开关”。 在新实例导数据的场…

【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 概述

【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 概述-CSDN博客 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建-CSDN博客 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行模式-CSDN博客 1、 Hadoop 是什么 &#xff08;1&#xff09;Hadoop是一个由Apache基…

第二百四十六回

我们在上一章回中介绍了"修改页面导航中遇到的问题"沉浸式状态样相关的内容&#xff0c;本章回中将介绍如何修改Avatar的大小.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在正常使用CirCleAvatar组件时可以通过该组件的radius属性来修改它的…

ssm基于web的素材网的设计与实现+vue论文

基于web的素材网站的设计与实现 摘要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。传统的素材信息管理模式&#xff0c;采用人工登记的方式保存相关数据&#xff0c;这种以人力为主的管理…

C语言中关于strcpy函数的理解

strcpy的功能是将源指向的字符串复制到另外一个字符串中 目标指向的数组的大小应该要足够长&#xff0c;避免让源字符串中的数据溢出 关于这个函数的具体用法&#xff0c;我们可以看看下面这个程序 注意&#xff1a;strcpy函数的头文件是<string.h>&#xff0c;我们在用…

rollup 插件输出生成钩子

✨专栏介绍 Rollup专栏是一个专门介绍Rollup打包工具的系列文章。Rollup是一个现代化的JavaScript模块打包工具&#xff0c;它可以将多个模块打包成一个或多个文件&#xff0c;以提高应用程序的性能和加载速度。 在Rollup专栏中&#xff0c;您将学习到如何安装和配置Rollup&a…

面向对象的三大特征之一多态

多态 概念 多态是同一个对象&#xff0c;在不同时刻表现出来不同的形态&#xff0c;称之为多态。 例如&#xff1a;水&#xff0c;我们把水理解成为一个对象&#xff0c;而水会有不同的形态&#xff0c;比如 液态水、冰块、水蒸气 多态的前提 有继承/实现关系&#xff08;继承…

OpenCV-15位运算

OpenCV中的逻辑运算就是对应位置的元素进行与、或、非和异或。 Opencv与Python不同的是&#xff1a;OpenCV中0的非反过来是255&#xff0c;255反过来是0。 但是Python中255非为-256。 一、非运算 使用API---cv.bitwise_not(str) 示例代码如下&#xff1a; import cv2 imp…

EasyRecovery2024永久免费版电脑数据恢复软件

EasyRecovery是一款操作安全、价格便宜、用户自主操作的非破坏性的只读应用程序&#xff0c;它不会往源驱上写任何东西&#xff0c;也不会对源驱做任何改变。它支持从各种各样的存储介质恢复删除或者丢失的文件&#xff0c;其支持的媒体介质包括&#xff1a;硬盘驱动器、光驱、…

小程序测试和APP测试的区别

今天看了一下关于如何测试小程序的教学视频&#xff0c;里面讨论了一个很经典的面试题&#xff1a;小程序测试和APP测试的区别&#xff0c;包括在之前的面试过程中也确实是遇到过这个问题&#xff0c;所以这次打算把它记录下来&#xff0c;也算是知识巩固了。 首先从测试的内容…

C++使用map插入insert数据(二进制数据和非二进制数据)接口封装+读取文件

1、定义编写代码 //生成insert sql语句std::string GetInsertsql(XDATA kv, std::string table);//插入非二进制数据bool Insert(XDATA kv, std::string table);//插入二进制数据bool InsertBin(XDATA kv, std::string table); std::string LXMysql::GetInsertsql(XDATA kv, s…

【51单片机系列】LCD1602液晶模块

本文是关于液晶显示屏的相关介绍。相对于静态数码管、动态数码管、LED点阵等&#xff0c;LCD1602液晶显示器能够显示更多的字符数字信息&#xff0c;并且也是常用的一种显示装置。 文章目录 一、LCD1602介绍1.1、LCD1602简介1.2、LCD1602常用指令1.3、LCD1602使用 二、LCD1602使…