MongoDB必备知识手册
一、认识之初
1、NoSQL简介
概念:
- NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
运用:
- NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
特点:
- 不支持SQL语法。存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据都是KV(key-value键值对)形式。
- NoSQL 的世界中没有一种通用的语言,每种 nosql 数据库都有自己的 api和语法,以及擅长的业务场景
产品种类:
- Mongodb
- Redis
- Hbase hadoop
- Cassandra hadoop
… …
2、NoSQL与SQL的比较
- 适用场景不同:sql数据库适合用于关系特别复杂的数据查询场景,nosql反之
- “事务”特性的支持:sql对事务的支持非常完善,而nosql基本不支持事务
- 两者在不断地取长补短,呈现融合趋势
SQL关系型数据库:
关系型数据库和非关系型数据库:
二、NoSQL - MongoDB
1、理解
MongoBD
是一个由C++语言编写的,介于关系型数据库和非关系型数据库之间的产品,是非关系型数据库当中,功能最丰富,最像关系型数据库的。是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似于JSON对象,它的字段值可以包含其他文档、数组及文档数组,非常灵活,旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB
是一个基于分布式物理上不在一起,是分开的。例如一个网页里面有html标签,该页面中加载了css样式,图片,还有视频,这些资源中,html,js,css可能在服务器A上面,图片可能在服务器B上面,视频可能在服务器 c 上面。MongoDB
支持多种平台,包扩Windows、Linux、MacOS、Solaris等,在官方网站都可找到相应的安装包。(需要注册)- 随着大数据的不断发展,非关系型数据库已经变得越来越重要,相关的产品也都得到了飞速发展。而其中
MongoDB
更是佼佼者,作为高性能开源文档数据库,MongoDB
以敏捷、可扩展和对企业应用友好而著称,因其操作简单、完全免费、源码公开等特点,受到了IT从业人员的青睐,并被广泛部署于实际的生产环境中。- 使用
MongoDB
的公司包括:BAT、360、Foursquare、Craiglist,、迪士尼、SAP、Intuit、EA等。
2、特点
易扩展:
NoSQL数据库种类繁多, 但是⼀个共同的特点都是去掉关系数据库的关系型特性。 数据之间⽆关系, 这样就⾮常容易扩展
⼤数据量, ⾼性能:
NoSQL数据库都具有⾮常⾼的读写性能, 尤其在⼤数据量下, 同样表现优秀。 这得益于它的⽆关系性, 数据库的结构简单
灵活的数据模型:
NoSQL⽆需事先为要存储的数据建⽴字段, 随时可以存储⾃定义的数据格式。 ⽽在关系数据库⾥, 增删字段是⼀件⾮常麻烦的事情。 如果是⾮常⼤数据量的表, 增加字段简直就是⼀个噩梦。
三、安装与配置
1、windows环境
目前,MongoDB版本都是4.0+。
-
选择该版本,安装到指定的磁盘
安装好后,查看文件内容。
bin文件夹中,要明白的是:1是关于客户端的启动程序,2是关于服务器的启动程序,有一个"d"字母的区别。中间的.cfg文件是关于配置的文件,可以更绑定ip和端口号。
-
我的电脑—>高级系统设置,配置bin目录到系统环境变量
-
创建数据库文件的存放位置
选择一个位置,新建文件夹来存放数据库文件(可以自行创建,也可以参考下面):
比如C盘,创建文件data\db,同bin目录下。
输入指令mongod --dbpath [自己的路径]
我的是mongod --dbpath "C:\Program Files\MongoDB\Server\4.0\data\db"
这段内容的含义是:指定存储位置,且开启服务器。这个不会弹出下一行输入框,说明MongoDB服务器已经成功开启。
注意:若路径在C盘,需要管理员省份运行终端!否则报错,而直接弹出下一行输入框。
- 再次检测是否成功
输入指定端口网址http://localhost:27017
,出现下面一段英文,则说明成功了。启动mongo.exe客户端即可。
使用安装包安装:
- 解压
tar -zxvf mongodb-linux-x86-64-ubuntu1604-3.4.0.tar
- 移动到/user/local/目录下
sudu mv mongodb-linux-x86-64-ubuntu1604-3.4.0.tar /user/local/mongodb
- 将可执行文件添加到path路径中(在~/.bashrc中添加)
export PATH="/usr/local/mongo/bin:$PATH"
alias sudo='sudo env PATH=$PATH'
2、Linux环境
# 安装
sudo apt-get install mongodb
# 删除
sudo apt-get --purge remove mongodb mongodb-clients mongodb-server
# 进入数据库
mongo XXX.XXX.XXX.XXX:27017
具体使用,如:启动,配置绑定ip远程连接等等。(选择"数据库"下的"MongoDB")
四、进入MongoDB数据库
具体是windows环境,Linux环境参考上上一个链接。
1.1、命令模式
命令行方式下启动服务进入数据库
(1)开启服务
- 新建一个存放MongoDB数据库的文件夹
- cd server中的bin目录中 (若已经配置环境变量,则省略该步骤)
- 输入
mongod.exe --dbpath "[创建的mongodb数据库的位置]"
(这服务开启部分同上)
(2)重新打开一个终端
- cd mongodb的bin目录 (若已经配置环境变量,则省略该步骤)
- 输入mongo.exe,即进入到mongodb数据库
1.2、本地模式
配置本地Windows MongoDB服务进入数据库
这样,可设置为开机自动启动,通过命令启动与关闭,大大提高效率。
-
在bin同级目录新建文件夹log,进入之后新建一个mongodb.log文件
-
创建
mongodb.log
文件
-
复制如下内容(注意路径按照自己配置的路径填写),以管理员模式运行命令提示符进行粘贴运行:
mongod --bind_ip 0.0.0.0 --logpath "C:\Program Files\MongoDB\Server\4.0\log\mongodb.log" --logappend --dbpath "C:\Program Files\MongoDB\Server\4.0\data\db" --port 27017 --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install
或者
mongod.exe -config "C:\Program Files\MongoDB\Server\4.0\bin\mongod.cfg" --install
这里的意思是绑定IP为0.0.0.0(即任意IP均可访问),指定日志路径、数据库路径和端口,指定服务名称。运行命令时,需要cd到exe文件目录下执行。 -
结果,直接指令开启服务,无需再建一个cmd来开启服务。
-
输入mongo.exe,即进入到mongodb数据库
安装服务:
见上3序号的内容,两种安装服务方式
启动服务:
net start MongoDB
关闭服务:
net stop MongoDB
移除服务:
cd到bin路径
mongod.exe --remove
1.3、添加密码
自行添加,自己玩可以不添加
> use admin
switched to db admin
> db.addUser('username','password')
连接
# 不选择数据库
mongo 134.567.345.23:27017 -u username -p password
# 选择数据库
mongo 134.567.345.23:27017/database -u username -p password
# 或者
mongo 134.567.345.23:27017/database -u username -p
# 输入密码
1.4、远程连接
打开:
更改:
0.0.0.0允许所有ip访问
bindIp: 0.0.0.0
五、MongoDB概念解析
MongoDB将数据存储为一个文档,数据结构由key==>value键值对组成,字段的值可以包含其他文档、数组以及数组文档
SQL术语/概念 | MongoDB术语/概念 | 解释说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表 / 集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 无 | 表连接/不支持 |
六、数据类型
1、MongoDB中的数据类型
下面为MongoDB中常用的几种数据类型:
序号 | 数据类型 | 说明 |
---|---|---|
1 | Object ID | 文档ID |
2 | String | 字符串,最常用。必须是有效的UTF-8 |
3 | Boolean | 存储一个bool值,为true或false |
4 | integer | 整数可以是32位或者是64位,这取决于服务器 |
5 | double | 存储浮点数 |
6 | array | 数组、列表 多个值存储到一个键 |
7 | object | 用于嵌入式的文档,即一个值为一个文档 |
8 | null | 存储null值 |
9 | TimeStamp | 时间戳,表示从1970-1-1到现在的总秒数 |
10 | Date | 存储当前⽇期或时间的UNIX时间格式 |
注意事项:
- 文档中的键值对是
有顺序
的 - 文档中的值,不仅可以是
字符串
,还可以是其他类型
,甚至可以是另一个文档
- mongodb
区分
类型和大小写 - mongodb的
主键
为_id - mongodb的
文档的key
是不可以有重复的 - 以_开头的键是
保留
的
2、json和bson类型
JSON:
什么是JSON: 一种被广泛使用的轻量级的数据交换格式,支持现今绝大多数的主流开发语言。
近几年mongodb则采用了类json的数据格式,在json上进行了丰富和增强,使得mongodb可以处理更大的数据类型。
格式:{“key”:“value”}
BSON:
什么是BSON: 一个类json的一种二进制形式存储的数据格式,简称binary json
特性: 轻量性、可遍历性、高效性
一个文档就相当于一个JSON数据结构
七、对于库和集合的操作
操作 | 语句 |
---|---|
查看所有的库 | show dbs / show databases |
创建、选择数据库 | use [数据库名称] |
创建集合(创建表) | db.createCollection(‘集合名称’) |
查看所有集合 | show collections |
删除集合 | db.[集合名].drop() |
删除当前数据库 | db.dropDatabase() |
注意:
- 如果选择的数据库不存在,则为创建数据库,存在则为切换
- 使用use创建的数据库是看不见的,除非在数据库中创建按集合9表),可以通过db/db.getName()去进行查看当前所在库
- 在mongodb数据库里,对于文档、集合的操作,统一用db(代表当前的库)
- 严格区分大小写
- 退出之前,最好use一下或者db一下,查看自己当前所在库,避免不显示数据库名。
八、文档的添加
1、insert() 添加单条/多条
操作 | 语句 | 实例 |
---|---|---|
插入一条文档 | db.[集合名].insert(文档) | db.myinfo.insert({“name”:“liyuhong”,“age”:“21”}) |
插入多条文档 | db.[集合名].insert([文档1,文档2…]) (列表方式存储) | db.myinfo.insert([{‘name’:‘mayun’,‘sex’:‘m’},{‘name’:‘liyuhong’,‘sex’:‘m’}]) |
注意:
- 如果插入多条没有给数组,则为插入
第一条
文档 - key的引号
可加可不加
,但是如果python操作mongodb,则必须加
引号,否则报错
2、insertOne() 单条/ insertMany() 多条
3.2版本后,还有如下用于插入文档的方式(更加语义化,推荐使用):
操作 | 语句 |
---|---|
向指定集合中插入一条文档数据 | db.collection.insertOne( { } ) |
向指定集合中插入多条文档数据 | db.collection.insertMany( [ { }, { } ] ) |
3、save() 添加、修改单条/多条
操作 | 语句 | 实例 |
---|---|---|
插入文档 | db.collection.save(文档) | db.user.save({‘name’:‘lyh’,‘age’:‘18’}) |
修改文档(其实就是对要修改的文档进行覆盖) | db.collection.save({’_id’:(id值),‘key’:‘value’…}) | db.user.save({ “_id” : ObjectId(“5ce7e28acfef3375fa66636c”), “name” : “li”, “age” : 18}) |
注意:
数据的添加建议使用insert(),推荐使用insertOne() / insertMany(),而save()主要作为数据的修改,虽然也有数据添加的功能。
九、 查询
1、普通查询
1.1 find()查询所有
格式:
db.[集合名].find(query,{field:1/0...})
参数:
query: 查询筛选条件,相当于mysql的where
field:1 / 0: 对某些field进行返回或者不返回(参数可选)
操作 | 语句 | 例子 |
---|---|---|
find查询所有 | db.[集合名].find() / db.[集合名].find({}) | db.myinfo.find() |
只对某些field进行显示 | db.[集合名].find({},{[域名]:1 / true}) | db.myinfo.find({},{name:1}) |
只对某些field进行不显示 | db.[集合名].find({},{[域名]:0 / false}) | db.myinfo.find({},{name:0}) |
指定_id不返回 | db.[集合名].find({},{_id:false}) | db.myinfo.find({},{_id:false}) |
错误的写法 | db.[集合名].find(name:true,sex:false) |
注意:
- _id
默认返回
,需要单独给_id设置false - inclusion和exclusion两种模式
不可混用
。因为混用无法推断其他key是否应该返回。 - 不需要查询条件也要使用{}进行
占位
- 1 / 0与true / false
效果一样
1.2 findOne()查询一条
格式:
db.[集合名].findOne(query,{field:1 / 0 ...})
实例:
查询一条文档,返回name域的值,其余都不返回,包括id(默认返回第一条)
db.myinfo.findOne({},{_id:false,name:true})
2、高级查询
2.1 统计数据条数count()
格式:
db.[集合名].find([query].count())
实例:
db.myinfo.find().count()
2.2 pretty展开来查看
格式:
db.[集合名].find([query]).pretty()
实例:
db.myinfo.find([{"_id" : ObjectId("5cefb46838dad496a7a8c166")}]).pretty()
2.3 条件查询操作符
注意:查询的时候,是否有引号影响查询结果,若插入时域名和域值加了引号,则查询也要加引号,否则查不到值。
符号 | 符号说明 | 实例 | 说明 |
---|---|---|---|
$gt | 大于 | db.[集合名].find({age:{$gt:‘18’}}) | 年龄大于18 |
$gte | 大于等于 | db.myinfo.find({age:{$gt:‘21’}}) | 年龄大于等于21 |
$lt | 小于 | db.myinfo.find({age:{$lt:‘21’}}) | 年龄小于21 |
$lte | 小于等于 | db.myinfo.find({age:{$gt:‘21’}}) | 年龄小于等于21 |
key:value | 等于 | db.myinfo.find({age:‘21’}) | 年龄等于21 |
_id:ObjectId(id值) | 使用id查询 | db.[集合名].find({"_id" : ObjectId(“5cefb5d838dad496a7a8c168”)}) | 根据id查询文档 |
/值/ | 模糊查询 | db.[集合名].find({name:/li/}) | 查询name中包含’li’的文档 |
/^值/ | 以…某个值作为开头 | db.[集合名].find({name:/^li/}) | 查询name以’li’开头的文档 |
/值$/ | 以…某个值作为结尾 | db.[集合名].find({name:/hong$/}) | 查询name以’hong’结尾的文档 |
$in | 在…内 | db.[集合名].find({‘age’:{$in:[‘18’,‘21’]}}) | 查询年龄为18或者21的文档 |
$nin | 不在…内 | db.myinfo.find({“age”:{$nin:[‘21’,‘21’]}}) | 查询年龄不为18或者21的文档 |
$ne | 不等于 | db.myinfo.find({‘age’:{$ne:‘21’}}) | 查询年龄不等于21的文档 |
2.4 AND查询
格式:
db.[集合名].find({key1:v1,key2:v2 ...})
实例:
查询年龄为21.且name以g结尾的文档
db.myinfo.find({name:/g$/,age:'21'})
查询age大于等于20,且小于25
db.myinfo.find({age:{$gte:'20',$lte:'25'}})
查询age大于等于20,且小于25,名字为liyuhong的文档
db.myinfo.find({age:{$gte:'20',$lte:'25'},name:'liyuhong'})
2.5 OR查询
格式:
db.[集合名].find({$or:[{条件1},{条件2} ...]})
实例:
查询name为liyuhong或mayun的文档
db.myinfo.find({$or:[{name:'liyuhong'},{name:'mayun'}]})
2.6 AND和OR组合使用
格式:
db.[集合名].find({query1,...,$or:[{query1},{query2} ...]})
实例:
查询姓名为liyuhong,年龄为18或者21的文档
db.myinfo.find({name:'liyuhong',$or:[{age:'18'},{age:'21'}]})
2.7 LIMIT取值
格式:
从第0个开始取num条文档
db.[集合名].find().limit(num)
实例:
db.myinfo.find().limit(2)
db.myinfo.find().limit(3).pretty()
2.8 SKIP跳过文档
从第0个开始跳过num条文档
格式:
db.[集合名].find().skip(num)
实例:
# 跳过2条文档
db.myinfo.find().skip(2)
2.9 LIMIT和SKIP混合使用
格式:
db.[集合名].find().skip(num).limit(num)
实例:
跳过两条,再读取2条文档(读取第3、4条文档)
db.myinfo.find().skip(2).limit(2)
2.10 SORT排序
格式:
# 1为升序,-1为降序
db.[集合名].find().sort({key:1/-1})
实例:
按照年龄进行升序和降序
db.myinfo.find().sort({age:-1})
2.11 投影
在查询到的返回结果中, 只选择必要的字段
格式:
db.集合名称.find({},{字段名称:1,...})
参数为字段与值:值为1表示显示, 值为0不显
特殊: 对于_id列默认是显示的, 如果不显示需要明确设置为0
实例:
# 不显示_id,但是显示item.name和age
db.cur.find({},{_id:0,'item.name':1,age:1})
2.12 聚合 - aggregation
聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。
db.集合名称.aggregate({管道:{表达式}})
在mongodb中,⽂档处理完毕后, 通过管道进⾏下⼀次处理。常用管道如下:
$match: 过滤数据, 只输出符合条件的⽂档
$count: 数据总计
$group: 将集合中的⽂档分组, 可⽤于统计结果
$limit: 限制聚合管道返回的⽂档数
$skip: 跳过指定数量的⽂档, 并返回余下的⽂档
$sort: 将输⼊⽂档排序后输出
$project: 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
$unwind: 将数组类型的字段进⾏拆分
$match (aggregation)
过滤文档,将符合指定条件的文档传递到下一个管道阶段。
$match
原型形式:{ $match:{<query>}}
$match
获取指定查询条件的文档。查询语法与 读操作查询 语法相同; 即 $match
不接受 原始聚合表达式 。
准备数据:
db.articles.insertMany([
{ "name" : "韩立", "score" : 80, "views" : 100 },
{ "name" : "韩立", "score" : 85, "views" : 521 },
{ "name" : "慕沛灵", "score" : 60, "views" : 1000 },
{ "name" : "陈巧倩", "score" : 55, "views" : 5000 },
{ "name" : "董萱儿", "score" : 60, "views" : 50 },
{ "name" : "菡云芝", "score" : 94, "views" : 999 },
{ "name" : "文思月", "score" : 95, "views" : 1000 }])
以下操作使用 $match
执行简单的相等匹配:
db.articles.aggregate(
[ { $match : { name : "韩立" } } ]
);
以下示例使用 $ match
管道运算符选择要处理的文档,然后将结果通过管道传递给 $group
管道运算符以计算文档计数:
db.articles.aggregate( [
{ $match: { $or: [ { score: { $gt: 70, $lt: 90 } }, { views: { $gte: 1000 } } ] } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
在聚合管道中,$ match
选择分数大于 70 且小于 90 或 views
大于或等于1000 的文档。然后将这些文档传送到 $group
以执行计数。
$count (aggregation)
准备数据
db.scores.insertMany([
{ "_id" : 1, "subject" : "History", "score" : 88 },
{ "_id" : 2, "subject" : "History", "score" : 92 },
{ "_id" : 3, "subject" : "History", "score" : 97 },
{ "_id" : 4, "subject" : "History", "score" : 71 },
{ "_id" : 5, "subject" : "History", "score" : 79 },
{ "_id" : 6, "subject" : "History", "score" : 83 }]
)
统计分数大于80的人的个数
- 找出所有分数大于八十分的人
- 统计所有人数
db.scores.aggregate(
[
{$match: {score: {$gt: 80}}},
{$count: "passing_scores"}
]
)
$group (aggregation)
按一些指定的表达式对文档进行分组,并为每个不同的分组输出到下一个阶段的文档。输出文档包含一个_id
按键包含不同组的字段。输出文档还可以包含存储由分组一些累加器表达式的值来计算字段 $group
的_id
字段。$group
并没有 责令其输出文档。
该 $group
有以下原型形式:
{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }
Accumulator Operator(累加操作) (aggregation)
<accumulator>
操作必须一下的操作之一:
名称 | 描述 |
---|---|
$avg | 返回数值的平均值。忽略非数字值。 |
$first | 返回每个组的第一个文档中的值。仅在文档按定义的顺序定义时才使用。 |
$last | 返回每个组的最后一个文档的值。仅在文档按定义的顺序定义时才使用。 |
$max | 返回每个组的最大值。 |
$min | 返回每个组的小值。 |
$sum | 返回数值的总和。忽略非数字值。 |
$push | 返回每个组的表达式值数组。 |
数据准备:
db.books.insertMany([
{ "_id" : 8751, "title" : "宴会", "author" : "但丁", "copies" : 2 },
{ "_id" : 8752, "title" : "神曲", "author" : "但丁", "copies" : 1 },
{ "_id" : 8645, "title" : "田园诗", "author" : "但丁", "copies" : 2 },
{ "_id" : 7000, "title" : "奥德赛", "author" : "荷马", "copies" : 10 },
{ "_id" : 7020, "title" : "伊利亚特", "author" : "荷马", "copies" : 10 }
])
以下聚合操作将书籍集合中的数据转换为按作者分组的标题。
db.books.aggregate(
[
{ $group : { _id : "$author", books: { $push: "$title" } } }
]
)
$limit (aggregation)
db.books.aggregate(
{ $limit : 3 }
);
$skip (aggregation)
db.books.aggregate(
{ $skip : 3 }
);
$sort (aggregation)
db.books.aggregate(
[
{ $sort : { copies : -1} }
]
)
十、修改
1、update() 修改单条 / 多条
结构:
db.[集合名].update(
<query>,
<update>,
{
upsert:<boolean>,
multi:<boolean>
}
)
参数的使用:
query: update的查询条件,类似于SQL中的where条件
update: update对象和一些更新的操作符,如:$inc $set
upsert: 可选,如果不存在update的记录,则是否插入。默认是false不插入。
multi: 可选,默认为false,即只更改找到的第一条记录,如果为true则更新全部。
update更新操作符 $set $inc
(1) $set 直接修改
实例:
将name为liyuhong的文档,key为age的域值改为18
db.myinfo.update({name:'liyuhong'},{$set:{age:'18'}})
(2) $inc 累加修改(只可用于数字类型)
将name为liyuhong的文档,key为age的域值累加5
db.myinfo.update({name:'liyuhong'},{$inc:{age:5}})
(3) multi参数的使用(只可用于数字类型)
将所有文档中age的值累加5
db.myinfo.update({},{$inc:{age:5}},{multi:true})
(4) upsert参数的使用
修改name为linjunjie的文档中age的域值为30,如果该记录不存在,则作为新文档插入
db.myinfo.update({name:'linjunjie'},{$set:{age:30}},{upsert:true})
(5) multi和upsert组合使用
将所有的文档中age的值累加5
db.myinfo.update({},{$inc:{age:5}},false,true)
2、updateOne() 单条 / updateMany() 多条
3.2版本以后
# 更新一条数据
db.[集合名].updateOne(query,update,true/false)
#更新多条数据,第三个参数为upsert
db.[集合名].updateMany(query,update,true/false)
3、replaceOne() 替换单条
db.replaceOne(query,update)
# 一对一替换
db.fanren.replaceOne({name:'杰克'},{'name':'艾伦'})
# 注意,不能包含原子操作符,包含原子操作符报错
[thread1] Error: the replace operation document must not contain atomic operators
十一、文档的删除
1、remove() 删除单条/多条
主体结构:
db.[集合名].remove(
<query>,
{
justOne:<boolean>
}
)
参数说明:
query: 可选,删除文档的条件
justOne: 可选,如果设为true或者1,则至少删除一个文档。默认为false
用法:
操作 | 语句 |
---|---|
默认将所有匹配到的文档进行删除 | db.[集合名].remove({条件}) |
只删除第一个匹配到的文档 | db.[集合名].remove({条件},true/1) |
只删除第一个匹配到的文档 | db.[集合名].remove({条件},{justOne:true}) |
实例:
删除年龄在30到40之间的文档
db.myinfo.remove({age:{$gte:30,$lte:40}})
删除所有文档
db.myinfo.remove({})
2、deleteOne() 单条 / deleteMany() 多条
3.2版本以后:
remove()方法限制已经过时,推荐使用以下方法
# 删除一条文档,不给参数删除第一条
deleteOne({xxx})
# 删除多条文档,不给参数则删除所有
deleteMany({xxx},{xxx}...)
十二、功能符号$
1、比较运算符
符号 | 含义 | 示例 |
---|---|---|
$lt | 小于 | {‘age’:{’$lt’:20}} |
$gt | 大于 | {‘age’:{’$gt’:20}} |
$lte | 小于等于 | {‘age’:{’$lte’:20}} |
$gte | 大于等于 | {‘age’:{’$gte’:20}} |
$ne | 不等于 | {‘age’:{’$ne’:20}} |
$in | 在范围内 | {‘age’:{’$in’:[20,23]}} |
$nin | 不在范围内 | {‘age’:{’$nin’:[20,23]}} |
$gt的使用,查询年龄大于20的:
db.myinfo.find({'age':{'$gt':20}})
2、逻辑运算符
Name | Description |
---|---|
$and | 返回与两个子句的条件匹配的所有文档。 |
$not | 返回与查询表达式不匹配的文档。 |
$nor | 返回无法匹配两个子句的所有文档。 |
$or | 返回与任一子句的条件匹配的所有文档。 |
$and的使用例子
db.fanren.find( { $and: [ { age: { $ne: 20 } }, { age: { $exists: true } } ] } )
and 运算里面可以嵌套 or
db.fanren.find( {
$and : [
{ $or : [ { age: { $ne: 20 } }, { age: { $exists: true } } ] },
{ $or : [ { tags: { $eq: "B" }}, { age : { $lt : 20 } } ] }
]
} )
3、其他功能符号
符号 | 含义 | 示例 | 示例含义 |
---|---|---|---|
$regex | 匹配正则表达式 | {‘name’:{’$regex’:’^l.*’}} | name以l开头 |
$exists | 属性是否存在 | {‘name’:{’$exists’:True}} | name属性存在 |
$type | 类型判断 | {‘name’:{’$type’:‘str’}} | name的类型为str |
$mod | 数字模操作 | {‘age’:{’$mod’:[5,0]}} | 年龄模5余0 |
$text | 文本查询 | {‘KaTeX parse error: Expected '}', got 'EOF' at end of input: text':{'search’:‘Kare’}} | text类型的属性中包含Kare字符串 |
$where | 高级条件查询 | {’$where’:‘obj.bug_count==obj.get_count’} | 自身购买数等于获得数 |
正则表达式$regex的使用:
db.myinfo.find({'name':{'$regex':'l'}})
关于这些操作更详细的用法:
操作-官方文档
十三、用python操作MongoDB数据库
1、安装扩展库且导入pymongo
pip install pymongo
需要pymongo库中的MongoClient类来连接MongoDb。
from pymongo import MongoClient
2、连接远程客户端
一般来说,只需传入MongoDB的IP和端口port即可。
mongodb端口不传,则默认为:27017。
实例:
from pymongo import MongoClient
# 只传入主机
conn = MongoClient('127.0.0.1')
# 给主机和端口
conn = MongoClient(host='127.0.0.1',port=27017)
# 传入连接字符串
conn = MongoClient(host='mongodb://localhost:27017/')
3、连接数据库和集合
连接数据库:
1.conn.[数据库名]
# 选择数据库
db=conn.test
2.conn[数据库名]
# 或者
db=conn['test']
连接集合:
数据库中包含很多集合(collection),类似于关系型数据库中的表。
1.collection = db.collection_name
collection = db.student
2.collection = db[collection_name]
# 连接student集合
collection = db['student']
4、插入数据
在 MongoDB
中,每条数据其实都有一个_id
属性来唯一标识。如果没有显式指明该属性, MongoDB
会自动产生一个ObjectId
类型的_id
属性。insert()
方法会在执行后返回_id
值。
(1)插入一条文档
每个文档为一个字典数据。
db.[集合名].insert({文档})
实例:
# 插入一条文档
result = db.myinfo.insert({'name':'liyuhong','age':21,'hobby':'play game'})
print(result)
# 结果
5932a68615c2606814c91f3d
(2)插入多条文档
多个文档(字典数据)包含在一个列表中表示
db.[集合名].insert([{文档1},{文档2}...])
实例:
# 插入多条文档
result = db.myinfo.insert([{'name':'mayun','hobby':'speaking'},{'name':'zhoujielun','hobby':'singing'}])
print(result)
# 结果
[ObjectId('5932a80115c2606a59e8a048'), ObjectId('5932a80115c2606a59e8a049')]
(3). 更新:官方已经不推荐使用insert()方法,有两个方法可以分别单条和多条插入文档。(建议在3.x以上版本使用的插入方法。)
插入一条文档
insert_one({文档})
插入多条文档
insert_many([{文档1},{文档2}...])
实例:
# 插入一条文档
result = db.myinfo.insert({'name':'liyuhong','age':21,'hobby':'play game'})
print(result)
print(result.inserted_id)
# 结果
<pymongo.results.InsertOneResult object at 0x10d68b558>
5932ab0f15c2606f0c1cf6c5
# 插入多条文档
result = db.myinfo.insert_many([{'name':'mayun','hobby':'speaking'},{'name':'zhoujielun','hobby':'singing'}])
print(result)
print(result.inserted_ids)
# 结果
<pymongo.results.InsertManyResult object at 0x101dea558>
[ObjectId('5932abf415c2607083d3b2ac'), ObjectId('5932abf415c2607083d3b2ad')]
(4). 获取ID:
每条数据其实都有一个_id属性来唯一表示。如果不指明该_id,则会自动产生一个ObjectId类型的_id属性。insert()方法会在执行后,返回该_id值。
单条文档id:
.inserted_id
多条文档id:
.inserted_ids
5、查询文档
(1) 查询所有(结果生成器)
db.[集合名].find()
返回结果是 Cursor 类型,它相当于一个生成器,可以通过遍历去获取所有的结果,其中每个结果都是字典类型。
实例:
# 查询所有
result = db.myinfo.find()
print(result) 返回结果类似一个迭代器,可以使用next方法取值
for i in result:
print(i)
# 结果
<pymongo.cursor.Cursor object at 0x1032d5128>
{'_id': ObjectId('593278c115c2602667ec6bae'), 'name': 'liyuhong'}
普通查询:
db.[集合名].find({query})
实例:
#带条件查询
result = db.myinfo.find({'name':'liyuhong'})
print(next(result))
# 结果
<pymongo.cursor.Cursor object at 0x1032d5128>
{'_id': ObjectId('593278c115c2602667ec6bae'), 'name': 'liyuhong'}
(2) 查询一条文档(结果为单个结果)
db.[集合名].find_one({query})
如果查询结果不存在,则会返回 None。
实例:
result = db.myinfo.find_one({'name':'liyuhong'})
print(type(result))
print(result)
<class 'dict'>
{'_id': ObjectId('5932a80115c2606a59e8a049'), 'name': 'liyuhong'}
(3) 根据Id来查询
需要导入ObjectId方法
from bson.objectid import objectId
# 按照Id进行查询
result = db.myinfo.find_one({"_id":ObjectId("5cebda671a8f4a314762160f")})
print(result)
{'_id': ObjectId('5932a80115c2606a59e8a049'), 'name': 'liyuhong'}
(4) 逻辑查询:
db.[集合名].find({query})
实例:
逻辑运算符:$gt
#带条件查询
result = db.myinfo.find({'age':{'$gt':20}})
print(next(result))
# 结果
<pymongo.cursor.Cursor object at 0x1032d5128>
{'_id': ObjectId('593278c115c2602667ec6bae'), 'name': 'liyuhong'}
(5) 模糊查询
db.[集合名].find({query})
实例:
import re
result = db.myinfo.find({'name':re.compile('l')})
result = db.myinfo.find({'name':{'$regex':'l'}})
print(next(result))
这里使用 $regex 来指定正则匹配
6、sort、limit、count、skip的使用
(1) sort排序
排序时,我们可以直接调用 sort 方法,并在其中传入排序的字段及升降序标志。
db.[集合名].find(query).sort('key',1/-1)
1和-1代表升序或降序,或传入字段,pymongo.ASCENDING,即:
db.[集合名].find(query).sort('key',pymongo.ASCENDING/DESCENDING)
实例:
result = db.myinfo.find().sort('age',1)
for i in result:
print(i)
(2)limit取值
使用limit指定要取的结果个数
db.[集合名].find(query).limit(num)
实例:
取出年龄最大的一条文档
# limit
result = db.myinfo.find().sort('age',-1).limit(1)
print(result)
(3)count计数
要统计查询结果有多少条数据,可以调用 count 方法。
db.[集合名].find(query).count()
返回符合条件的数据条数
(4)skip跳过、偏移
需要取中间某几个元素,这时可以利用 skip 方法偏移几个位置,比如偏移 2,就代表忽略前两个元素,得到第 3 个及以后的元素
db.[集合名].find().skip(num)
注意:
在数据量非常庞大的时候,比如在查询千万、亿级别的数据库时,最好不要使用大的偏移量,因为这样很可能导致内存溢出。此时可以使用类似如下操作来查询:
from bson.objectid import ObjectId
collection.find({'_id': {'$gt': ObjectId('593278c815c2602678bb2b8d')}})
7、update修改
对原数据进行修改,或者增加,或者数据值的增加
update方法其实是官方不推荐使用的方法,在这里分别使用udate_one和update_many方法
(1) update
更新删除原来其他字段:
db.[集合名].update({条件},{'$set':{替换内容}})
更新不影响其他字段:
db.[集合名].update({条件},{替换内容})
原值增加指定的值:
db.[集合名].update({条件},{'$inc':{指定值}})
实例1:
db.myinfo.update({'name':'mayun'},{'$set':{'age':40}})
# {'ok': 1, 'nModified': 1, 'n': 1, 'updatedExisting': True}
# ok表示执行成功,nModified代表影响的数据条数
实例2:
condition = {'age': {'$gt': 20}}
result = collection.update_one(condition, {'$inc': {'age': 1}})
print(result)
print(result.matched_count, result.modified_count)
# 结果
<pymongo.results.UpdateResult object at 0x10b8874c8>
1 1
(2)update_one第一条符合的数据进行更新
db.[集合名].update_one({条件}, {'$set': {更新的数据}})
例子:
condition = {'name': 'Li'}
student = collection.find_one(condition)
student['age'] = 22
result = collection.update_one(condition, {'$set': student})
print(result)
print(result.matched_count, result.modified_count)
第 2 个参数不能再直接传入修改后的字典,而是需要使用 {’$set’: student} 这样的形式,其返回结果是 UpdateResult 类型。然后分别调用 matched_count 和 modified_count 属性,可以获得匹配的数据条数和影响的数据条数。
结果:
<pymongo.results.UpdateResult object at 0x10d17b678>
1 0
(3)update_many将所有符合条件的数据都进行更新
db.[集合名].update_many({条件}, {'$set': {更新的数据}})
实例:
condition = {'age': {'$gt': 20}}
result = collection.update_many(condition, {'$inc': {'age': 1}})
print(result)
print(result.matched_count, result.modified_count)
<pymongo.results.UpdateResult object at 0x10c6384c8>
3 3
匹配结果不止一条,所有结果都会更新。
(4)获取匹配数据的条数和受影响的数据跳数
.matched_count 匹配数据条数
.modified_count 受影响数条数
8、remove修改
(1) 删除
db.[集合名].remove({query})
删除name为zhoujielun的文档:
db.myinfo.remove({'name':'zhoujielun'})
# 结果
{'ok': 1, 'n': 1}
(2) 全部删除
db.[集合名].remove()
(3) 3.x以上使用,官方建议使用的方法:
删除第一个符合条件的文档
delete_one({query})
实例:
result = db.myinfo.delete_one({'name':'mayun'})
print(result)
print(result.deleted_count)
# 结果
<pymongo.results.DeleteResult object at 0x10e6ba4c8>
1
删除所有符合条件的文档
delete_many({query})
实例:
result = db.myinfo.delete_many({'age':{'$lt':25}})
print(result)
print(result.deleted_count)
# 结果
<pymongo.results.DeleteResult object at 0x10e6ba4c8>
4
返回结果都是 DeleteResult 类型
(4) 获得删除文档条数
.delete_count
9、关闭连接
conn.close()
10、其他操作
另外,PyMongo 还提供了一些组合方法,如 find_one_and_delete、find_one_and_replace 和 find_one_and_update,它们分别用于查找后删除、替换和更新操作,其使用方法与上述方法基本一致。
另外,我们还可以对索引进行操作,相关方法有 create_index、create_indexes 和 drop_index 等。
可见其他CRUD操作官方文档
还有该库的其他使用操作
pymongo库的其他操作
十四、参考文档
MongoDB安装下载官网
MongoDB官方文档(总)
MongoDB官方文档(核心)
MongoDB中文文档
静览的个人站点
菜鸟中文文档
其他CRUD操作官方文档
pymongo库的其他操作
功能符号$-官方文档
十五、更新时间
第一次更新 2020.4.26
第二次更新 2020.6.17