0%

MongoDB学习笔记

MongoDB非关系型数据库的使用

前言

传统的关系型数据库(如MySQL),在数据操作的“三高”需求以及应对Web2.0的网站需求面前,显得力不从心。
解释:“三高”需求:

High performance - 对数据库高并发读写的需求。

Huge Storage- 对海量数据的高效率存储和访问的需求。

High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求。

MongoDB可应对“三高”需求。

具体的应用场景如:
1)社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。

2)游戏场景,使用 MongoDB存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。

3)物流场景,使用MongoDB存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。

4)物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。

5)视频直播,使用 MongoDB 存储用户信息、点赞互动信息等。

这些应用场景中,数据操作方面的共同特点是:

(1)数据量大

(2)写入操作频繁(读写都很频繁)

(3)价值较低的数据,对事务性要求不高

对于这样的数据,我们更适合使用MongoDB来实现数据的存储。

什么时候选择MongoDB

在架构选型上,除了上述的三个特点外,如果你还犹豫是否要选择它?可以考虑以下的一些问题:

  • 应用不需要事务及复杂 join支持

  • 新应用,需求会变,数据模型无法确定,想快速迭代开发

  • 应用需要2000-3000以上的读写QPS(更高也可以)

  • 应用需要TB甚至PB级别数据存储

  • 应用发展迅速,需要能快速水平扩展

  • 应用要求存储的数据不丢失

  • 应用需要99.999%高可用
  • 应用需要大量的地理位置查询、文本查询

如果上述有1个符合,可以考虑 MongoDB,2个及以上的符合,选择 MongoDB 绝不会后悔。

思考:如果用MySQL呢?

答:相对MySQL,可以以更低的成本解决问题(包括学习、开发、运维等成本)

简介

MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是最像关系型数据库(MySQL)的非关系型数据库。

它支持的数据结构非常松散,是一种类似于 JSON的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。

MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。

体系结构

MySQLMongoDB对比

image-20220311140141447

SQL 术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
嵌入文档 MongoDB通过嵌入式文档来替代多表连接
primary key 主键,MongoDB自动将_id字段设置为主键

MongoDB特点

MongoDB主要有如下特点:

(1)高性能:

MongoDB提供高性能的数据持久性。特别是对嵌入式数据模型的支持减少了数据库系统上的I/O活动。

索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。(文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、地理位置索引可用于构建各种O2O 应用)

mmapv1wiredtigermongorocks(rocksdb)in-memory等多引擎支持满足各种场景需求。

Gridfs解决文件存储的需求。

(2)高可用性:

MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余。

(3)高扩展性:

MongoDB提供了水平可扩展性作为其核心功能的一部分。

分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展)

从3.4开始,MongoDB支持基于片键创建数据区域。在一个平衡的集群中,MongoDB将一个区域所覆盖的读写只定向到该区域内的那些片。

(4)丰富的查询支持:

MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。

(5)其他特点:如无模式(动态模式)、灵活的文档模型

部署安装

去官网(https://www.mongodb.com/try/download/community)下载`mongodb`安装包`mongodb-windows-x86_64-5.0.6-signed.msi`

打开安装完毕后,在目录...\MongoDB\Server\5.0下创建配置文件mongo.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 数据库路径
dbpath=D:\Program Files\MongoDB\Server\5.0\data

# 日志输出文件路径
logpath=D:\Program Files\MongoDB\Server\5.0\log\mongod.log

# 错误日志采用追加模式
logappend=true

# 启用日志文件,默认启用
journal=true

# 这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false
quiet=true

# 端口号 默认为27017
port=27017

打开cmd输入mongo --version

返回版本信息说明安装成功

image-20220311141639975

1. 数据库操作(db)

1.1 选择和创建数据库

选择和创建数据库的语法格式:

1
use 数据库名称

如果数据库不存在则自动创建,例如,以下语句创建 spitdb 数据库:

1
use spitdb

查看有权限查看的所有的数据库命令

1
2
3
show dbs

show databases

注意 : 在 MongoDB中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。

查看当前正在使用的数据库命令

1
db

MongoDB 中默认的数据库为 test,如果你没有选择数据库,集合将存放在 test数据库中。

有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。

  • admin : 从权限的角度来看,这是”root”数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
  • local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  • config : 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

1.2 数据库的删除

MongoDB 删除数据库的语法格式如下:

1
db.dropDatabase()

提示:主要用来删除已经持久化的数据库

2 集合操作(Collection)

集合,类似关系型数据库中的表。
可以显示的创建,也可以隐式的创建。

2.1 集合的显示创建

基本语法格式:

1
db.createCollection("name")

参数说明:

  • name: 要创建的集合名称

例如:创建一个名为 mycollection 的普通集合。

1
db.createCollection("mycollection")

查看当前库中的表:show tables命令

1
2
3
show collections

show tables

2.2 集合的隐示创建

当向一个集合中插入一个文档的时候,如果集合不存在,则会自动创建集合。

提示:通常我们使用隐式创建文档即可。

2.3 集合的删除

集合删除语法格式如下:

1
2
3
db.collection.drop()

db.集合.drop()

返回值

如果成功删除选定集合,则 drop()方法返回 true,否则返回false

例如:要删除mycollection集合

1
db.mycollection.drop()

3 文档基本的增删改查(Document)

文档(document)的数据结构和JSON基本一样。

所有存储在集合中的数据都是BSON格式。

3.1 文档的插入

3.1.1 单个文档的插入

要向comment的集合(表)中插入一条测试数据:

1
db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明媚","userid":"1001","nickname":"Rose","createdatetime":new Date(),"likenum":NumberInt(10),"state":null})

提示:
1)comment集合如果不存在,则会隐式创建
2)mongo中的数字,默认情况下是double类型,如果要存整型,必须使用函数NumberInt(整型数字),否则取出来就有问题了。
3)插入当前日期使用new Date()
4)插入的数据没有指定 _id ,会自动生成主键值
5)如果某字段没值,可以赋值为null,或不写该字段。

执行后,如下,说明插入一个数据成功了。

1
WriteResult({ "nInserted" : 1 })

3.1.2 批量插入

批量插入多条文章评论:

1
2
3
4
5
6
db.comment.insertMany([
{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},
{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},
{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},
{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},
{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}]);

因为批量插入由于数据较多容易出现失败,因此,可以使用try catch进行异常捕捉处理,测试的时候可以不处理。如(了解):

1
2
3
4
5
6
7
8
9
10
try {
db.comment.insertMany([
{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},
{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},
{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},
{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},
{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}]);
} catch (e) {
 print (e);
}

3.2 文档的基本查询

3.2.1 查询所有

如果我们要查询comment集合的所有文档,我们输入以下命令

1
2
3
db.comment.find()

db.comment.find({})

按一定条件来查询,比如查询userid1003的记录

1
db.comment.find({userid:'1003'})

只返回符合条件的第一条数据

1
db.comment.findOne({userid:'1003'})

3.2.2 投影查询

如果要查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定的字段)。

如:查询结果只显示 _iduseridnickname :

1
2
3
>db.comment.find({userid:"1003"},{userid:1,nickname:1})
{ "_id" : "4", "userid" : "1003", "nickname" : "凯撒" }
{ "_id" : "5", "userid" : "1003", "nickname" : "凯撒" }

默认 _id会显示。

如:查询结果只显示 、 useridnickname ,不显示_id

1
2
3
>db.comment.find({userid:"1003"},{userid:1,nickname:1,_id:0})
{ "userid" : "1003", "nickname" : "凯撒" }
{ "userid" : "1003", "nickname" : "凯撒" }

再例如:查询所有数据,但只显示_iduseridnickname :

1
2
3
4
5
6
7
>db.comment.find({},{userid:1,nickname:1})
{ "_id" : ObjectId("6226c931d0da8b8df3c925"), "userid" : "1001", "nickname" : "Rose" }
{ "_id" : "1" }
{ "_id" : "2", "userid" : "1005", "nickname" : "伊人憔悴" }
{ "_id" : "3", "userid" : "1004", "nickname" : "杰克船长" }
{ "_id" : "4", "userid" : "1003", "nickname" : "凯撒" }
{ "_id" : "5", "userid" : "1003", "nickname" : "凯撒" }

3.3 文档的更新

3.3.1 覆盖的修改

如果我们想修改_id为1的记录,点赞量为1001,输入以下语句:

1
db.comment.update({_id:"1"},{likenum:NumberInt(1001)})

执行后,我们会发现,这条文档除了 likenum字段其它字段都不见了,

3.3.2 局部修改

为了解决这个问题,我们需要使用修改器$set来实现,命令如下:
我们想修改_id为2的记录,浏览量为889,输入以下语句:

1
db.comment.update({_id:"2"},{$set:{likenum:NumberInt(889)}})

3.3.3 批量修改

更新所有用户为1003的用户的昵称为 凯撒大帝 。

1
2
3
4
//默认只修改第一条数据
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒2"}})
//修改所有符合条件的数据
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒大帝"}},{multi:true})

提示:如果不加后面的参数,则只更新符合条件的第一条记录

3.3.4 列值增长的修改

如果我们想实现对某列值在原有值的基础上进行增加或减少,可以使用 $inc运算符来实现。
需求:对3号数据的点赞数,每次递增1

1
db.comment.update({_id:"3"},{$inc:{likenum:NumberInt(1)}})

3.4 文档的删除

删除文档的语法结构:

1
db.集合名称.remove(条件)

以下语句可以将数据全部删除,请慎用

1
db.comment.remove({})

如果删除_id=1的记录,输入以下语句

1
db.comment.remove({_id:"1"})

4 文档的分页查询

4.1 统计查询

统计查询使用count()方法,语法如下:

1
db.collection.count(query, options)

4.1.1 统计所有记录数

统计comment集合的所有的记录数:

1
db.comment.count()

4.1.2 按条件统计记录数

例如:统计userid1003的记录条数

1
db.comment.count({userid:"1003"})

提示:
默认情况下 count() 方法返回符合条件的全部记录条数。

4.2 分页列表查询

可以使用limit()方法来读取指定数量的数据,使用skip()方法来跳过指定数量的数据。

基本语法如下所示:

1
db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

如果你想返回指定条数的记录,可以在find方法后调用limit来返回结果(TopN),默认值20

1
db.comment.find().limit(3)

skip 方法同样接受一个数字参数作为跳过的记录条数。(前N个不要),默认值是0

1
db.comment.find().skip(3)

分页查询:需求:每页2个,第二页开始:跳过前两条数据,接着值显示3和4条数据

1
2
3
4
5
6
//第一页
db.comment.find().skip(0).limit(2)
//第二页
db.comment.find().skip(2).limit(2)
//第三页
db.comment.find().skip(4).limit(2)

4.3 排序查询

sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。

语法如下所示:

1
2
3
db.COLLECTION_NAME.find().sort({KEY:1})

db.集合名称.find().sort(排序方式)

例如:

userid降序排列,并对访问量进行升序排列

1
db.comment.find().sort({userid:-1,likenum:1})

提示:

skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先sort(), 然后是 skip(),最后是显示的limit(),和命令编写顺序无关。

5 文档的更多查询

5.1 正则的复杂条件查询

MongoDB的模糊查询是通过正则表达式的方式实现的。格式为:

1
2
3
db.collection.find({field:/正则表达式/})

db.集合.find({字段:/正则表达式/})

提示:正则表达式是js的语法,直接量的写法。

例如,我要查询评论内容包含“开水”的所有文档,代码如下:

1
db.comment.find({content:/开水/})

如果要查询评论的内容中以 “专家”开头的,代码如下:

1
db.comment.find({content:/^专家/})

5.2 比较查询

<, <=, >, >= 这个操作符也是很常用的,格式如下:

1
2
3
4
5
db.集合名称.find({ "field" : { $gt: value }}) // 大于: field > value
db.集合名称.find({ "field" : { $lt: value }}) // 小于: field < value
db.集合名称.find({ "field" : { $gte: value }}) // 大于等于: field >= value
db.集合名称.find({ "field" : { $lte: value }}) // 小于等于: field <= value
db.集合名称.find({ "field" : { $ne: value }}) // 不等于: field != value

示例:查询评论点赞数量大于 700的记录

1
db.comment.find({likenum:{$gt:NumberInt(700)}})

5.3 包含查询

包含使用$in操作符。 示例:查询评论的集合中userid字段包含1003或1004的文档

1
db.comment.find({userid:{$in:["1003","1004"]}})

不包含使用 $nin操作符。 示例:查询评论集合中userid字段不包含1003和1004的文档

1
db.comment.find({userid:{$nin:["1003","1004"]}})

5.4 条件连接查询

我们如果需要查询同时满足两个以上条件,需要使用$and操作符将条件进行关联。(相当于SQLand) 格式为:

1
$and:[ {  },{  },{ } ]

示例:查询评论集合中 likenum大于等于700 并且小于2000的文档:

1
db.comment.find({$and:[{likenum:{$gte:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]})

如果两个以上条件之间是或者的关系,我们使用 操作符进行关联,与前面 and的使用方式相同格式为:

1
$or:[ {  },{  },{   } ]

示例:查询评论集合中 userid为1003,或者点赞数小于1000的文档记录

1
db.comment.find({$or:[ {userid:"1003"} ,{likenum:{$lt:1000} }]})

6 常用命令小结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
选择切换数据库:use articledb
插入数据:db.comment.insert({bson数据})
查询所有数据:db.comment.find();
条件查询数据:db.comment.find({条件})
查询符合条件的第一条记录:db.comment.findOne({条件})
查询符合条件的前几条记录:db.comment.find({条件}).limit(条数)
查询符合条件的跳过的记录:db.comment.find({条件}).skip(条数)
修改数据:db.comment.update({条件},{修改后的数据}) 或db.comment.update({条件},{$set:{要修改部分的字段:数据})
修改数据并自增某字段值:db.comment.update({条件},{$inc:{自增的字段:步进值}})
删除数据:db.comment.remove({条件})
统计查询:db.comment.count({条件})
模糊查询:db.comment.find({字段名:/正则表达式/})
条件比较运算:db.comment.find({字段名:{$gt:值}})
包含查询:db.comment.find({字段名:{$in:[值1,值2]}})或db.comment.find({字段名:{$nin:[值1,值2]}})
条件连接查询:db.comment.find({$and:[{条件1},{条件2}]})或db.comment.find({$or:[{条件1},{条件2}]})

7. Python操作MongoDB数据库

7.1 下载pymongo

1
pip install pymongo

7.2 连接MongoDB数据库

1
2
3
4
5
6
7
8
from pymongo import MongoClient

# 连接mongodb数据库
conn = MongoClient(host="127.0.0.1")
# 选择数据库
db = conn.articledb
# 选择文档
my_set = db.comment

7.3 操作数据库

7.3.1 插入数据

1
2
3
4
5
6
# ###################插入数据################
# 在集合中插入文档
my_set.insert_one({"articleid": "100002", "likenum": 3200})
# 在集合中插入多条文档
my_set.insert_many([{"articleid": "100002", "likenum": 3200},
{"articleid": "100003", "likenum": 3300}])

7.3.2 查询数据

1
2
3
4
5
6
7
# ###############查询数据#################
# 查询数据
list(my_set.find())
# 条件查询
list(my_set.find({"articleid": "100003"}))
# 条件查询,只返回第一条
list(my_set.find_one({"articleid": "100003"}))

7.3.3 更新数据

1
2
3
4
5
6
7
# ###############更新数据#################
# 更新第一条
my_set.update_one({"articleid": "100003"}, {"$set": {"likenum": 3232}})
list(my_set.find({"articleid": "100003"}))
# 更新所有
my_set.update_many({"articleid": "100003"}, {"$set": {"likenum": 3232}})
list(my_set.find({"articleid": "100003"}))

7.3.4 删除数据

1
2
3
4
5
6
7
8
9
# ##############删除数据#################
# 删除符合条件的第一条
my_set.delete_one({"articleid": "100003"})
list(my_set.find({"articleid": "100003"})) # 发现只有一条文档了
my_set.insert_one({"articleid": "100003", "likenum": 3211}) # 再次插入文档

# 删除符合条件的所有文档
my_set.delete_many({"articleid": "100003"})
list(my_set.find({"articleid": "100003"})) # 删除后发现已经没有符合条件的文档了

7.3.5 条件操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# ##################条件操作符#####################
# 查询likenum小于1000的文档
list(my_set.find({"likenum": {"$lt": 1000}}))
# 查询likenum大于1000小于等于2000的文档
list(my_set.find({"$and": [{"likenum": {"$gt": 1000}}, {"likenum": {"$lte": 2000}}]}))
# 查询likenum小于1000或者大于2000的文档
list(my_set.find({"$or": [{"likenum": {"$lt": 1000}}, {"likenum": {"$gt": 2000}}]}))

# ##################排序################
list(my_set.find({}, {"likenum":1}).sort([("likenum", 1)]))

# #################限制输出#####################
list(my_set.find({}, {"likenum":1}).sort([("likenum", 1)]).limit(2))

# #################跳过指定数量的数据################
list(my_set.find({}, {"likenum":1}).sort([("likenum", 1)]).limit(2).skip(1))

# ###################找出包含集合中的数据#####################
list(my_set.find({"_id":{"$in": ('3', '5', '6')}}, {"likenum":1}))

# #################### 找出包含集合中全部的数据 ############
list(my_set.find({"_id":{"$all": ('3', '4')}}, {"likenum":1})) # 只包含部分,不输出
list(my_set.find({"_id":{"$all": ('3',)}}, {"likenum":1})) # 全部包含才输出
list(my_set.find({"_id":{"$all": ('4',)}}, {"likenum":1})) # 全部包含才输出

7.3.6 数组操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ################# 给数组增加值 ###########
# 增加数组记录
my_set.insert_one({"nickname": "lm", "state": [1, 2, 3]})
list(my_set.find({"nickname": "lm"}))
# 增加单个值
my_set.update_one({"nickname": "lm"}, {"$push": {"state": 2}})
list(my_set.find({"nickname": "lm"}))
# 增加多个值
my_set.update_one({"nickname": "lm"}, {"$pushAll": {"state": [3, 3, 3]}})
list(my_set.find({"nickname": "lm"}))

# ############## 给数组删除值 ################
my_set.update_one({"nickname": "lm"}, {"$pop": {"state": 1}}) # 移除最后一个元素
list(my_set.find({"nickname": "lm"}))
# 根据值将第一个符合条件的文档元素进行删除
my_set.update_one({"nickname": "lm"}, {"$pull": {"state": 3}})
list(my_set.find({"nickname": "lm"}))
# 根据之将所有包含元素的文档元素进行删除
my_set.update_many({"nickname": "lm"}, {"$pullAll": {"state": [1, 2]}}) # 根据值进行删除
list(my_set.find({"nickname": "lm"}))

7.3.7 多级目录

1
2
3
4
5
6
7
8
9
10
11
12
13
# ############# 多级目录 ################
my_set.insert_one({"nickname": "lm2",
"contact": {"email": "123147@qq.com", "iphone": "1122131233344"}})
list(my_set.find({"nickname": "lm1"}))
# 多级目录用.进行连接
list(my_set.find({"contact.email": "1234567@qq.com"}))

result = my_set.find_one({"contact.email": "1234567@qq.com"})
result["contact"]["email"]

# 多级路径修改操作
my_set.update_one({"contact.email": "1234567@qq.com"}, {"$set": {"contact.email": "736704198@qq.com"}})
list(my_set.find({"contact.email": "736704198@qq.com"}))
-------------本文结束感谢您的阅读-------------