MongoDB的介绍
MongoDB是免费开源的跨平台NoSQL数据库,命名源于英文单词humongous,意思是「巨大无比」,可见开发组对 MongoDB 的定位。与关系型数据库不同,MongoDB的数据类似于JSON格式的二进制文档存储:
例如:
{
name: "MongoDB",
age: 18,
hobbies: ["python", "mongo"]
}
文档型的数据存储方式有几个重要好处:
- 文档的数据类型可以对应到语言的数据类型,如数组类型(Array)和对象类型(Object)
- 文档可以嵌套,有时关系型数据库涉及几个表的操作,在 MongoDB 中一次就能完成,可以减少昂贵的连接花销;
- 文档不对数据结构加以限制,不同的数据结构可以存储在同一张表
MongoDB的适用场景
-
网站数据
Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性
-
缓存
由于性能很高,Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载
-
大尺寸、低价值的数据
使用传统的关系型数据库存储一些大尺寸低价值数据时会比较浪费,在此之前,很多时候程序员往往会选择传统的文件进行存储
-
高伸缩性的场景
Mongo 非常适合由数十或数百台服务器组成的数据库,Mongo 的路线图中已经包含对MapReduce 引擎的内置支持以及集群高可用的解决方案
-
用于对象及JSON 数据的存储
Mongo 的BSON 数据格式非常适合文档化格式的存储及查询
MongoDB的行业具体应用
-
游戏场景
使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
-
物流场景
使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
-
社交场景
使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
-
物联网场景
使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
-
直播
使用 MongoDB 存储用户信息、礼物信息等
如何抉择是否使用MongoDB
(有一个yes就可以选择MongoDB,两个以上yes,选MongoDB绝对不后悔 )
| 应用特征 | Yes/No |
|---|---|
| 应用不需要复杂事务及复杂join支持 | yes |
| 新应用,需求会变,数据模型无法确定,想快速迭代开发 | ? |
| 应用需要2000-3000以上的读写QPS(更高也可以) | ? |
| 应用需要TB甚至 PB 级别数据存储 | ? |
| 应用发展迅速,需要能快速水平扩展 | ? |
| 应用需要大量的地理位置查询、文本查询 | ? |
| 应用需要99.999%高可用 | ? |
MongoDB与关系型数据库比较
| RDMS | MongoDB |
|---|---|
| database(数据库) | database(数据库) |
| table (表) | collection( 集合) |
| row( 行) | document( BSON 文档) |
| column (列) | field (字段) |
| index(唯一索引、主键索引) | index (支持地理位置索引、全文索引 、哈希索引) |
| join (主外键关联) | embedded Document (嵌套文档) |
| primary key(指定1至N个列做主键) | primary key (指定_id field做为主键) |
什么是BSON
BSON是一种类似于JSON的二进制形式的存储格式,简称Binary JSON,它和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。BSON有三个特点:轻量性、可遍历性、高效性。
下表列出了MongoDB中Document可以出现的数据类型:
| 数据类型 | 说明 | document举例 |
|---|---|---|
| String | 字符串 | {key:“cba”} |
| Integer | 整型数值 | {key:2} |
| Boolean | 布尔型 | {key:true} |
| Double | 双精度浮点数 | {key:0.23} |
| ObjectId | 对象id,用于创建文档的id | {_id:new ObjectId()} |
| Array | 数组 | {arr:[“jack”,“tom”]} |
| Timestamp | 时间戳 | { createTime: new Timestamp() } |
| object | 内嵌文档 | {student:{name:“zhangsan”,age:18}} |
| null | 空值 | {key:null} |
| Date或者ISODate | 日期时间 | {birthday:new Date()} |
| Code | 代码 | {setPersonInfo:function(){}} |
Windows安装与启动MongoDB
MongoDB有企业版和社区版两种,企业版是要收费的,社区版是免费的,只是学习和简单运用的话,社区版就够了。
社区版下载网址:https://www.mongodb.com/try/download/community

下载稳定版本(5.0.9)

解压即用。
启动MongoDB:通过命令启动
mongod.exe --dbpath=path --logpath=path
其中:dpath指定数据存储的位置,logpath指定日志存储的位置。指定的路径位置一定要存在
在创建mongo_home目录下创建start.bat文件输入目录,如下:
D:\mongodb5_0_9\bin\mongod.exe --dbpath="d:\mongodb5_0_9\data" --logpath="d:\mongodb5_0_9\log\log.txt"
MongoDB通过配置文件管理参数
在MongoDB根目录创建mongo.conf配置文件,内容如下:
#数据库路径
dbpath=D:\Program Files\mongodb-win32-x86_64-windows-4.4.6\db
#日志输出文件路径
logpath=D:\Program Files\mongodb-win32-x86_64-windows-4.4.6\logs\mongo.log
#错误日志采用追加模式
logappend=true
#启用日志文件,默认启用
journal=true
#这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false
quiet=true
#端口号 默认为27017
bind_ip=0.0.0.0
# 启用权限验证,使用账号密码登录
#auth=true
启动方式:
mongod.exe -f 配置文件地址
脚本启动:
D:\mongodb5_0_9\bin\mongod.exe -f d:\mongodb5_0_9\mongo.conf
Linux安装MongoDB
MongoDB下载官网:https://www.mongodb.com/try/download/community
下载安装包:https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.9.tgz
先下载依赖与安装包:
yum install wget -y
yum install vim -y
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.9.tgz
然后解压安装:
tar -zxvf mongodb-linux-x86_64-rhel70-5.0.9.tgz
mv mongodb-linux-x86_64-rhel70-5.0.9 mongodb5
接着配置环境变量:vim ~/.bashrc
修改PATH变量:
PATH=/opt/mongodb5/bin:$PATH:$HOME/bin
创建数据存放目录
sudo mkdir -p /var/mongo/log
sudo mkdir -p /var/mongo/data
touch /var/mongo/log/mongo.log
开启服务
mongod --dbpath /var/mongo/data --logpath /var/mongo/log/mongo.log --fork
配置文件管理参数
在Mongo文件夹增加配置文件, 命令如下:
touch /opt/mongodb5/mongo.cfg
vim /opt/mongodb5/mongo.cfg
添加如下内容:
#数据库路径
dbpath=/var/mongo/data
#日志输出文件路径
logpath=/var/mongo/log/mongo.log
#错误日志采用追加模式
logappend=true
#启用日志文件,默认启用
journal=true
#这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false
quiet=true
#端口号 默认为27017
bind_ip=0.0.0.0
port=27017
MongoDB GUI管理工具
MongoDB数据库默认的管理工具是(CLI)Shell命令行,对于专业的DBA来说比较容易上手,但是对于普通人员GUI可视化工具更方便使用。我们来介绍下MongoDB可视化工具。
独立软件GUI软件
目前在网络要有多种图形软件比如:
- Robo 3T 免费
- Navicat for MongoDB 收费
- MongoDB Compass 社区版 免费
- NoSQLBooster(mongobooster) 免费
- NOSQLCLIENT 收费
- Aqua Data Studio Mongo 收费
- 等等
Robo 3T使用
下载:https://studio3t.com/download-studio3t-free
https://download.studio3t.com/studio-3t/windows/2022.6.1/studio-3t-x64.zip
打开后,选择“New Connection”新建链接 ===> Next
输入“Connection name”链接名 ===> 输入“Server”与“Port”Mongo地址与端口号 ===> Save
VSCode集成GUI插件
安装插件 ===> Database Client

Docker 安装 MongoDB
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。
访问Explore Docker's Container Image Repository | Docker Hub,
搜索mongo镜像https://hub.docker.com/search?q=mongo
查看可用的镜像
获取你想要拉取的镜像:
docker pull mongo:5.0.9
查看已下载的镜像
docker images
创建挂载目录
mkdir d:\docker_app\mongodb_data --创建保存数据目录
创建并运行 mongo 容器
docker run -itd --name mongo5 -p 27017:27017 -v D:\docker_app\mongodb_data\:/data/db mongo:5.0.9
停止和启动服务:
docker stop/start mongo5
MongoDB基础命令
查看数据库:
列出所有在物理上存在的数
show dbs;
切换数据库/创建数据库
如果数据库不存在,则指向数据库,但不创建,直到插入数据或创建集合时数据库才被创建
use 数据库名;
删除当前数据库
删除当前指向的数据库 如果数据库不存在,则什么也不做
use 数据库名
db.dropDatabase()
创建集合
单纯创建集合命令
db.createCollection("集合名")
注意:无需手动创建集合, 向不存在的集合中第一次添加数据时,集合会自动被创建出来
查看集合
showtables; //5.0.9不再支持
show collections;
删除集合
db.集合名.drop();
Mongo_文档的添加
MongoDB将文档存储在集合中。集合类似于关系数据库中的表。如果集合不存在,MongoDB 会在首次存储该集合的数据时创建该集合。
编写语法为
| 函数名 | 含义 |
|---|---|
| save( ) | 保存文档。文档不存在时,新创建一个文档; 文档存在,更新文档 |
| insert( ) | 插入文档,可以保存单文档,也可以是多文档 |
| insertOne( ) | 插入一个文档 |
| insertMany( ) | 插入多个文档 |
注意:插入文档时,如果不指定_id参数,MongoDB会为文档分配一个唯一的ObjectId
例子:
db.集合名.save(document)
db.集合名.insert(document)
db.集合名.insertOne(document)
db.集合名.insertMany([document,document])
Mongo_文档的修改
编写语法为:
db.集合名.函数名()
| 函数名 | 含义 |
|---|---|
update( <query>, <update> ,{multi: <boolean>}) | 参数query:查询条件,类似sql语句update中where部分 参数update:更新操作符,类似sql语句update中set部分 参数multi:可选,默认是false,表示只更新找到的第一条记录,值为true表示把满足条件的文档全部更新 |
updateOne( <query>, <update>) | 更新一条数据 |
updateMany( <query>, <update>) | 更新多条数据 |
replaceOne(<query>, <update>) | 只能更新整文档 |
注意:更新的字段若不存在,会生成一个相应字段
例子:
# 只更新找到的第一条,并且会修改结构
db.person.update({name:"zs"},{age:16})
# 只更新数据,为不更新文档结构
db.person.update({name:"zs"},{$set:{age:123})
# 更新所有找到匹配的数据
db.person.update({name:"zs"},{$set:{age:123}}, {multi: true})
# 只更新找到的第一条
db.person.updateOne({name:"zs"},{age:16})
# 更新所有找到匹配的数据
db.person.updateMany({name:"zs"},{age:16})
Mongo_文档的删除
| 函数名 | 含义 |
|---|---|
remove( <query>) | 参数query:匹配符合的删除条件数据 |
deleteOne( <query>) | 更新一条数据 |
deleteMany( <query>) | 更新多条数据 |
删除集合所有文档:
db.集合名.deleteMany({})
删除指定条件的文档
db.集合名.deleteMany({ status : "A" })
最多删除1个指定条件的文档
db.集合名.deleteOne( { status: "D" } )
Mongo_文档的查询
若要从集合中选择文档,可以使用 find()或者findOne() 方法。若要选择集合中的所有文档,请将空文档作为查询筛选器文档传递给该方法。
编写语法为
db.集合名.函数名()
| 函数名 | 含义 |
|---|---|
find( <{条件文档}>) | 查找到所有匹配数据 |
findOne( <{条件文档}>) | 只返回匹配的第一个数据 |
运算符
| 语法 | 操作 | 格式 |
|---|---|---|
| $eq | 等于 | {:} |
| $lt | 小于 | {:{$lt:}} |
| $lte | 小于或等于 | {:{$lte:}} |
| $gt | 大于 | {:{$gt:}} |
| $gte | 大于或等于 | {:{$gte:}} |
| $ne | 不等于 | {:{$ne:}} |
| $or | 或 | {$or:[{},{}]} |
| $in | 在范围内 | {age:{$in:[val1,val2]}} |
| $nin | 不在范围内 | {age:{$nin:[val1,val2]}} |
例子:
db.person.find({age:{$gt:16}})
db.person.find({$or:[{age:{$gte:18}},{name:"zs"}])
模糊匹配:使用//或$regex编写正则表达式
db.person.find({name:/^zs/})
db.person.find({name:{$regex:'^zs'}}})
自定义查询使用$where后面写一个函数,返回满足条件的数据
db.person.find({$where:function(){return this.age>20}}) # 5.0版本不能用了
db.person.find({$where:"this.age==23"});
db.person.find("this.age >23");
db.person.find('this.country=="吴国" || this.age==23');
limit用于读取指定数量的文档
db.集合名称.find().limit(NUMBER)
skip用于跳过指定数量的文档
db.集合名称.find().skip(2)
sort用于对结果集进行排序
db.集合名称.find().sort({字段:1,...})
count用于统计结果集中文档条数
db.集合名称.find({条件}).count()
db.集合名称.count({条件})
db.stu.find({gender:true}).count()
db.stu.count({age:{$gt:20},gender:true})
$exists判断是否有某个字段
db.集合名称.find({'field':{$exists:true}})
distinct去重
db.集合名称.distinct(field)
db.集合名称.distinct(field,{过滤条件 })
样例数据 首先插入一批文档,再进行查询
db.person.insert([{"name":"司马懿","country":"魏国","age":35},
{"name":"张辽","country":"魏国","age":34},
{"name":"徐晃","country":"魏国","age":24},
{"name":"夏侯惇","country":"魏国","age":23},
{"name":"夏侯渊","country":"魏国","age":23},
{"name":"庞德","country":"魏国","age":23},
{"name":"张郃","country":"魏国","age":34},
{"name":"李典","country":"魏国","age":41},
{"name":"乐进","country":"魏国","age":34},
{"name":"典韦","country":"魏国","age":12},
{"name":"曹洪","country":"魏国","age":21},
{"name":"曹仁","country":"魏国","age":11},
{"name":"诸葛亮","country":"蜀国","age":20},
{"name":"关羽","country":"蜀国","age":32},
{"name":"张飞","country":"蜀国","age":23},
{"name":"马超","country":"蜀国","age":53},
{"name":"黄忠","country":"蜀国","age":23},
{"name":"赵云","country":"蜀国","age":32},
{"name":"魏延","country":"蜀国","age":42},
{"name":"关平","country":"蜀国","age":12},
{"name":"周仓","country":"蜀国","age":42},
{"name":"关兴","country":"蜀国","age":23},
{"name":"张苞","country":"蜀国","age":12},
{"name":"周瑜","country":"吴国","age":32},
{"name":"吕蒙","country":"吴国","age":11},
{"name":"甘宁","country":"吴国","age":23},
{"name":"太史慈","country":"吴国","age":23},
{"name":"程普","country":"吴国","age":24},
{"name":"黄盖","country":"吴国","age":28},
{"name":"韩当","country":"吴国","age":23},
{"name":"周泰","country":"吴国","age":29},
{"name":"蒋钦","country":"吴国","age":19},
{"name":"丁奉","country":"吴国","age":17},
{"name":"徐盛","country":"吴国","age":27}
])
Mongo_聚合操作分组与过滤
MongoDB 中聚合(aggregate)主要用于处理多个文档(诸如统计平均值,求和等),并返回计算后的数据结果。
- 对多个文档进行分组
- 对分组的文档执行操作并返回单个结果
- 分析数据变化
db.集合名称.aggregate([{管道:{表达式}}])

管道命令之$group
按照某个字段进行分组
$group是所有聚合命令中用的最多的一个命令,用来将集合中的文档分组,可用于统计结果
使用示例如下
db.stu.aggregate(
{$group:
{
_id:"$country",
counter:{$sum:1}
}
}
)
其中注意点:
db.db_name.aggregate是语法,所有的管道命令都需要写在其中_id表示分组的依据,按照哪个字段进行分组,例如:需要使用$gender表示选择这个字段进行分组$sum:1表示把每条数据作为1进行统计,统计的是该分组下面数据的条数
常用表达式
表达式:处理输⼊⽂档并输出 语法:表达式:'$列名' 常⽤表达式:
$sum: 计算总和, $sum:1 表示以⼀倍计数$avg: 计算平均值$min: 获取最⼩值$max: 获取最⼤值$push: 在结果⽂档中插⼊值到⼀个数组中
管道命令之$match
$match用于进行数据的过滤,是在能够在聚合操作中使用的命令,和find区别在于$match 操作可以把结果交给下一个管道处理,而find不行
使用示例如下:
查询年龄大于20的人
db.person.aggregate([
{$match:{age:{$gt:20}}}
])
查询年龄大于20的魏国的人数
db.person.aggregate([
{$match:{age:{$gt:20}}},
{$group:{_id:"$country",counter:{$sum:1}}}
])
Mongo_索引的基本使用
索引概述
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录
这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对应用的性能是非常致命的
创建索引
MongoDB使用 createIndex() 方法来创建索引
db.集合名.createIndex(keys, options)
语法中 Key 值为要创建的索引字段,1 为指定按升序创建索引,如果想按降序来创建索引指定为 -1 即可
注意
- 在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名
- MongoDB默认所有的集合在_id字段上有一个索引。
样例
db.person.createIndex({"name":1})
索引的查看 默认情况下_id是集合的索引,查看方式:
db.集合名.getIndexes()
删除索引
db.集合名.dropIndex({'索引名称':1})
db.person.dropIndex({name:1})
db.person.getIndexes()
Mongo中唯一索引\复合索引
唯一索引
在默认情况下mongdb的索引的值是可以相同的,创建唯一索引之后,数据库会在插入数据的时候检查创建索引域的值是否存在,如果存在则不会插入该条数据,但是创建索引仅仅能够提高查询速度,同时降低数据库的插入速度
添加唯一索引的语法
db.集合名.createIndex({"字段名":1}, {"unique":true})
利用唯一索引进行数据去重
根据唯一索引指定的字段的值,如果相同,则无法插入数据
db.person.createIndex({"name":1}, {"unique":true})
db.person.insert({name: 'test10000'})
复合索引
在进行数据去重的时候,可能用多个字段来做数据的唯一性,这个时候可以考虑建立复合索引来实现。
建立复合索引的语法:
db.collection_name.createIndex({字段1:1,字段2:1})
建立索引注意点
根据需要选择是否需要建立唯一索引
索引字段是升序还是降序在单个索引的情况下不影响查询效率,但是带复合索引的条件下会有影响
数据量巨大并且数据库的读出操作非常频繁的时候才需要创建索引,如果写入操作非常频繁,创建索引会影响写入速度
Mongo_Python操作数据
先在python安装相应库
pip install pymongo==4.2.0
官方文档:PyMongo 4.13.0 documentation
#引入包pymongo
import pymongo
#连接,创建客户端
client = pymongo.MongoClient("localhost", 27017)
client = pymongo.MongoClient('mongodb://localhost:27017/')
#获得数据库test1
db = client.test1
db = client['test']
#获得集合movie
collection = db.movie
collection = db['movie']
#添加数据
#增加一条
m1={name:'300集',actor:'高总',level:10}
m1_id = movie.insert_one(s1).inserted_id
#增加多条
mids = movie.insert_many([movie1,movie2])
注意原insert方法也可以实现上面的功能,但是在PyMongo 3.x的版本已经不推荐使用
查找数据
- find() 返回一个生成器对象
- find_one() 返回一条数据
result = movie.find_one()
result = movie.find_one({'name':'300集'})
result = movie.find_one({'_id':OjectId('5932a80115c2606a59e8a049')})
result = movie.find_one({level:{'$gt':1}})
results = movie.find()
比较符号
| 符号 | 含义 | 示例 |
|---|---|---|
| $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]}} |
功能符号
| 符号 | 含义 | 示例 | 示例含义 |
|---|---|---|---|
| $regex | 匹配正则表达式 | {'name': {'$regex': '^M.*'}} | name以M开头 |
| $exists | 属性是否存在 | {'name': {'$exists': True}} | name属性存在 |
| $type | 类型判断 | {'age': {'$type': 'int'}} | age的类型为int |
| $mod | 数字模操作 | {'age': {'$mod': [5, 0]}} | 年龄模5余0 |
| $text | 文本查询 | {'$text': {'$search': 'Mike'}} | text类型的属性中包含Mike字符串 |
| $where | 高级条件查询 | {'$where': 'obj.fans_count == obj.follows_count'} | 自身粉丝数等于关注数 |
# 获取文档个数
count = movie.count_documents()
# 排序
results = collection.find().sort('name', pymongo.ASCENDING)
# 偏移/分页
collection.find().sort('name', pymongo.ASCENDING).skip(2).limit(2)
# 更新
args = {"name": "曹操"}
student.update_one(args, {'$set':{field:value}}})
result = collection.update_many(query, {'$set': {field:value}})
# 删除
result = collection.remove({'name': '300集'}) # 4.2版本不支持
result = collection.delete_one({'name': '300集'})
result = collection.delete_many({'age': {'$lt': 25}})
2091

被折叠的 条评论
为什么被折叠?



