MongoDB的使用及CRUD操作

MongoDB

一、基本介绍

概念

MongoDB是存储JSON文档的非关系型数据库,结构如下图:

image-20211030224316478

一个数据库中有很多集合,一个集合中有很多文档。

运行

使用Docker运行MongoDB:

docker run --name mymongo -v /mymongo/data:/data/db -d mongo
# --name给容器起别名

MongoDB默认使用27017端口

查看日志

docker logs 容器名称

Mongo Shell

Mongo Shell 是用来操作MongoDB的JS客户端

# 运行Mongo Shell
docker exec -it 容器名称 mongo

二、增删改查操作

存储在MongoDB的每篇文档都有一个专属的id,称为文档主键,存储在 _id 字段中:

  • 主键具有唯一性(不同文档的主键不能重复),支持除数组之外的所有数据类型,一篇文档可以作为另一篇文档的主键,称为复合主键。
  • 如果创建文档时没有指定主键,则会默认创建一个对象主键 ObjectId("包含创建时间的字串")
    • 提取对象主键的创建时间:ObjectId("xxx").getTimestamp()

2.1 创建文档

  • 使用 db.集合.insert() 或者 db.集合.save() 命令
    • insert命令又分为insertOne、insertMany、insert

基本语法:

db.<collection>.insertOne(
	<document>,
    {
    
    
    	writeConcern: <document>
    }
)
  • <collection> 要替换成文档存放的集合,此集合如果不存在则自动创建
  • <document> 要替换成写入的文档本身
  • writeConcern: <document> 定义了本次文档创建操作的安全写级别
    • 安全写级别用来判断一次数据库写入操作是否成功
    • 安全写级别越高,丢失数据的风险就越低,然而写入操作的延迟也就越高
    • 如果不指定安全写级别,则MongoDB会使用默认的级别
  • 注意:安全写级别和文档的 JSON 键值对不在一个大括号中,需要另写一个大括号

演示:

运行Mongo Shell

docker exec -it 容器名称 mongo

使用test数据库

use test
# 数据库存在则切换到该数据库,数据库不存在则自动创建该数据库并切换到该数据库

查看test数据库的所有集合

show collections
# 现在新创建的test数据库中还没有集合

将文档写入accounts集合

db.accounts.insertOne(
	{
    
    
        _id: "account1",
        name: "alice",
        balance: 100
    }
)

指定了主键,但没有指定安全写级别

运行结果

{
    
     "acknowledged" : true, "insertedId" : "account1" }
  • "acknowledged" : true 表示安全写级别被启用,此时显示的是默认的安全写级别的状态
  • "insertedId" : "account1" 显示了被写入文档的主键

如果insertOne遇到了错误

使用重复的主键id创建一个新文档:

image-20211031002028387

出现了错误:

image-20211031002210468

可以捕获异常:

image-20211031002247779

库函数print打印出的异常消息更加直观:

image-20211031002401481

自动生成主键id

省略 _id 字段即可:

image-20211031002536190

创建多个文档

基本语法:

image-20211031002610211
  • ordered 参数用来决定是否要按顺序写入这些文档,取值为true或false,默认取值为true
  • 如果 ordered 的取值为false,则MongoDB可以打乱文档顺序写入,加快写入速度

示例:

image-20211031003020892

如果insertMany遇到了错误

image-20211031003257326
  • 顺序写入时,一旦遇到了错误,剩余的文档无论正确与否,都不会被执行
  • 乱序写入时,即使某些文档造成了错误,但剩余的正确文档仍然会被写入

创建多个或单个文档

基本语法:

image-20211031003551219

示例:

image-20211031003622946

save命令

基本语法:

image-20211031003702958
  • save指令处理一个新文档时,会调用insert指令

复合主键

image-20211031004104293
  • 复合主键也要满足唯一性,否则报错
    • 复合主键中的内容相同但是键值对的顺序不同不认为主键重复

2.2 读取文档

基本语法:

db.集合.find(<query>, <projection>)

  • query 表示 JSON 格式的查询条件(可选),为空则表示没有查询条件,即查询全部文档
  • projection 表示对结果进行投影操作(可选)
    • 可以返回文档的部分字段,提高效率(注意不是返回部分文档)
    • 如果省略投影字段,则返回所有符合条件的完整字段的文档
    • 无论是否使用投影,查询结果的个数都是一样的,只不过使用了投影会使得返回的文档不显示全部字段

2.2.1 读取全部文档

db.集合.find()

更直观的显示文档:db.集合.find().pretty()

2.2.2 匹配查询

image-20211031101911250 image-20211031102319210

2.2.3 比较操作符

image-20211031102433257 image-20211031141542785

**注意:**本来查询条件是key-value共用一个大括号,现在是比较符和value还要另占一个大括号。

示例1:

image-20211031102527757

注意:$ne 会查询出不包含查询字段的文档,可以理解为不包含自然就不等于。

示例2:

比较运算符也可以按照字典顺序比较:

image-20211031141508493

示例3:

image-20211102205501853

注意:

  1. in、nin 操作符对应的value值要放在一个数组中
  2. nin 会筛选出不包含查询字段的文档

示例4:

in结合正则表达式使用:

image-20211115214303522

2.2.4 逻辑操作符

image-20211102205732190

**注意:**使用逻辑操作符还需要再加一层大括号。

示例1:

image-20211102205856227

**注意:**not 也会筛选出不包含查询字段的文档。

示例2:

image-20211102210014928

简化写法1(用在不同字段上):

image-20211102210237250

简化写法2(用在同一字段上):

image-20211102210314660

示例3:

image-20211102210425505

**注意:**nor 会筛选出不包含查询字段的文档。

2.2.5 字段操作符

$exists :匹配是否存在指定字段的文档

$type:匹配字段类型符合查询值的文档

示例1:

image-20211102210642158

示例2:

原本会得到不包含查询字段的文档,加上这个条件后不包含查询字段的文档就不会被查询到:

image-20211102210746866

示例3:

image-20211102210939164

示例4:

image-20211102211005913

2.2.6 数组操作符

image-20211115213031171

all示例:

image-20211115213648847

elemMatch示例:

image-20211115213922603

2.3 文档游标

执行 db.集合.find() 返回的是一个文档集合的游标:var myCursor = db.集合.find(),在不迭代游标的情况下,只列出前20个文档。

可以使用游标下标直接访问文档集合中的某一个文档:

image-20211115214721234

遍历完游标中所有的文档之后,或者在10分钟之后,游标便自动关闭。

image-20211115214828765

游标函数:

  1. hasNext & next

    image-20211115214942657
  2. forEach

    image-20211115214954606
  3. limit & skip

    image-20211115215229209

    注意:limit(0) 表示返回所有结果。

  4. count

    基本语法:cursor.count(<boolean>),括号中为空则默认是false。

    当括号中为 false 时,limit 和 skip 二者无效;当括号中为 true 时,才会使用 limit 和 skip 的效果:

    image-20211116211525122
  5. sort

    1表示从小到大的正向排序,-1表示从大到小的逆向排序:

    image-20211116211644258
  6. 两个注意

    • skip 在 limit 之前执行
    • sort 在 skip 和 limit 之前执行
    image-20211116211923609

文档投影:

使用文档投影可以只返回文档的部分字段:1表示返回,0表示不返回:

image-20211116213311315

注意:除了文档主键之外,不可以同时使用包含和不包含两种投影操作:

image-20211116213746785

2.4 更新文档

基本语法:

db.集合.update(<query>, <update>, <options>)

  • query 定义了被更新文档的筛选条件,与 find 中的筛选条件作用一致
  • update 定义了更新结果
  • options 定义了一些更新操作的参数

注意:以上三者都是可选的。

示例:

如果可选的 <update> 中不包含任何更新操作符,更新命令将会使用 <update> 文档直接替换集合中对应的整篇文档(全部字段)

image-20211116221939312

注意:

  1. 主键字段是不可以更改的,如果一定要使用主键字段,<update> 中的主键字段值务必与原内容一致。
  2. 如果有多篇文档可以匹配到 <query>,使用不包含更新操作符的 <update> 更新整篇文档时只会更新第一篇。

更新操作符:

如果可选的 <update> 中包含更新操作符,更新命令将会使用 <update> 文档替换集合中对应文档的特定字段

image-20211116222411862

$set:

更新或新增字段:

image-20211117171504119

更新数组中的字段:

image-20211117171742325

注意:如果插入时超过了数组的范围,导致数组中有空位,则空位默认填充null。

$unset:

删除字段:

image-20211117172341362

注意:如果删除的是数组元素,则不会改变数组长度,只会将对应元素置为null。

$rename:

重命名文档:

image-20211117173038137
  1. 如果重命名不存在的文档,则不会改变原文档内容

  2. 如果新的字段名已经存在,则会置空(unset)原文档同名的字段,并将所要修改的字段重命名

  3. 内嵌文档重命名:

    image-20211117173752956

    注意:对于内嵌数组,此方式无法使用,会报错。

$inc & $mul:

image-20211117174144585 image-20211117174208498

注意:

  1. 这两个命令只能作用在数字字段上
  2. 当作用在不存在的字段时,$inc 会创建字段,并将字段值设置为指定的增减值;$mul 会创建字段,但是字段值为0

$min & $max:

比较原文档值与新值之后更新值:

image-20211117175326205

注意:如果被更新的字段不存在,这两个命令会创建字段,字段值为更新值。

数组更新操作符:

这些操作符只能作用在数组字段上:

image-20211117175840513

$addToSet:

image-20211117180116819

注意:

  1. 如果要插入的值已经存在于数组字段中,此命令不会再插入重复值

  2. 此命令插入文档或数组时,内容相同顺序不同不认为重复

  3. 一次添加多个值:

    image-20211117180533783 image-20211117180606440

$pop:

删除数组字段的第一个元素或者最后一个元素,1表示删除最后一个元素,-1表示删除第一个元素:

image-20211117211436683

注意:删除数组中最后一个元素后,数组会置空。

$pull & $pullAll:

从数组字段中删除特定元素:

image-20211117212353876 image-20211117212447740

$push:

向数组字段中添加元素:

image-20211117212546401

2.5 删除文档

基本语法:

db.集合.remove(<query>, <options>)

  • query:查询条件
    • 筛选条件为空表示删除所有文档
  • options:删除操作的参数
image-20211117212755912

默认情况下,remove 命令会删除所有符合筛选条件的文档,如果只想删除满足筛选条件的第一篇文档,可以使用 justOne 参数:

image-20211117213023249

2.6 删除集合

remove 命令可以删除集合内的所有文档,但是不会删除集合,删除集合的方式如下:

image-20211117213123837

猜你喜欢

转载自blog.csdn.net/weixin_49343190/article/details/121388500