note

robomongo:免费、开源的 MongoDB 跨平台桌面管理工具,支持 Windows、Linux、Mac

MongoDB

一、介绍|安装

1.1. 使用场景

mysql是关系型数据库,支持事务;mongodb,redis非关系型数据库,不支持事务

mysql、mongodb、redis的使用根据如何方便进行选择:

1.2. 数据类型

1.3. 安装

window下的mongod mongodb安装完后,就把bin路径添加到环境变量中去; 配置MongoDB服务

1、创建配置文件 mongod.cfg 内容:

systemLog: destination: file path: E:\MongoDB\log\mongod.log storage: dbPath: E:\MongoDB\db # 注意这是一个目录,根绝自己实际情况改

2、安装MongoDB服务

mongod –config “E:\MongoDB\mongod.cfg” –install

启动服务:net start MongoDB 关闭服务:net stop MongoDB 移除服务:mongod –remove

链接服务:mongo

二、MongoDB简单使用

2.1. 基本信息|合集

查看数据集基本信息:

查看所有数据库: show dbs /show databases 切换数据库: use db_name # 当使用一个不存在的数据库,是看不到的,往里面插入数据后,就会出来 查看当前的数据库: db 删除当前的数据库: db.dropDatabase()

集合的创建使用:

创建集合: db.createCollection(name,options) 例如: db.createCollection(“students”) # 创建一个名为students的集合 Ps:可以不手动创建集合,不存在的集合中第一次加入数据时,集合会被创建出来 db.createCollection(“students”, { capped : true, size : 10}) #参数capped:默认值为false表示不设置上限,值为true表示设置上限,10个字节,大于后数据就会像队列那样覆盖掉

查看集合: show collections 删除集合: db.集合名称.drop() # db.teachers.drop()

2.2. 增删改查

db.my_stu.insert({name: “zhangsan”, age: 23, gender: “male”}) db.my_stu.insert({_id: “20210114”, name: “lisi”, age: 25}) # 这是给了_id,不给会默认生成 保存:db.集合名称.save(document)

#如果文档的_id已经存在则修改,如果文档的_id不存在则添加 # 如果是insert插入时指定的_id已经存在,则会报错


db.my_stu.update({name:’zhangsan’},{name:’new_zhangsan’}) #更新一条,注意整个这条数据都只剩下name字段了,其它的就没了,基本不用这

db.my_stu.update({name: “lisi”}, {$set: {name: “a_new_lisi”}}) #更新一条,且值更新这一条的name字段,其它原本的建值都还在

db.my_stu.update({}, {$set: {gender:”male”}}, {multi:true}) # 更新全部,因为前面query那里还没有条件,会把所有数据的gender都改成male,(有的数据没有gender这个字段都会被添加进去)

db.my_stu.update({name: “lisi”}, {$set: {gender:”female”}}, {multi:true}) #跟上同理,这就是把name=”lisi”的数据的gender都改成female

db.test01.update({name: “wangwu”}, {$set:{name: “zhaoliu”}}, {multi: true}) #要是是多个name: wangwu, 但是其它键的值不一样,想把每条name:wangwu都更新成name:zhaoliu

Ps: “multi update only works with $ operators” # 就是说这个multi必须和$一起使用才有效


db.my_stu.remove({age: 10}) # 这会把所有的age=10的数据删除的 db.test01.remove({age: 10}, {justOne:true}) # 就只删除查询到的第一条

三、高级查询

3.1. 简单查询

db.my_stu.find() # 查询所有数据 db.my_stu.findOne({age:20}) # 就只是看一条数据 db.my_stu.find({age:20}).pretty() # 格式化一下数据,看起来美观

3.2. 比较运算符

db.my_stu.find({age:{$gte:18}}) # 选择年龄大于等于18的

3.3. 范围运算符

”$in”,”$nin”: 查询是否在某个范围内的值 查询年龄为18、16的学生:db.my_stu.find({age: {$in:[18, 16]}})

3.4. 逻辑运算符

​ 相当于就是多个条件

3.5. 正则、limit、skip

两个可以同时使用

3.6. 自定义查询、投影

使用==$where==后面写一个函数,返回满足条件的数据:

查询年龄大于30的学生

db.my_stu.find({$where: function() {return this.age> 30}}) # 返回满足条件的数据 db.my_stu.find({​$where: function() {return this.age> 30}}, {name:1}) # 这就是只返回name字段 db.my_stu.find({$where: function() {return this.age> 30}}, {_id: 0, name:1, age:1})

3.7. 排序、count

db.my_stu.find().sort({age: 1}) # 按照age的升序去排;-1就是降序 db.my_stu.find({age: {$gt: 18}}).sort({age: -1, name: 1}) # 先选出年龄大于18的,再按照age降序排,相同时再按照name,还可以再跟

db.my_stu.find({age: {$gte: 18}}).count() # age大于等于18的学生的人数 或者直接来 db.my_stu.count({age: {$gte: 18}}) # 直接计数就是db.my_stu.count()

3.8. 消除重复

db.my_stu.distinct(“hometown”) db.my_stu.distinct(“hometown”, {age: {$gt: 20}}) # 还可以跟条件

四、聚合|aggregrate

​ 聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。 ​ 语法:db.集合名称.aggregate({管道:{表达式}})

常用管道: ​ $group:将集合中的文档分组,可用于统计结果; ​ ​$match:过滤数据,只输出符合条件的文档; ​ ​$project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果; ​ ​$sort:将输入文档排序后输出; ​ ​$limit:限制聚合管道返回的文档数; ​ ​$skip:跳过指定数量的文档,并返回余下的文档; ​ $unwind:将数组类型的字段进行拆分。

​ 表达式:处理输入文档并输出 ​ 语法:表达式:’$列名’ 常用的表达式如下: ​ $sum:计算总和,​$sum:1表示以一倍计数; ​ $avg:计算平均值; ​ $min:获取最小值; ​ $max:获取最大值; ​ $push:在结果文档中插入值到一个数组中; ​ $first:根据资源文档的排序获取第一个文档数据; ​ $last:根据资源文档的排序获取最后一个文档数据。

4.1. $group

将集合中的文档分组,可用于统计结果:

#按照性别进行分组

#按照hometown分组,获取不通组的平均年龄

group by null 这样就是来统计整个文档的信息;group分组时_id的依赖字段为null

group还可以按照多个字段分组

​ 格式:{$group: {_id: {自定义名字字段1: "$country", 自定义名字字段2: "$provience", ....}}} # 多个字段就一起这样以字典的形式放在 _id 后。

db.my_stu.aggregrate( {$group: {_id: {country: “$country”, provience: “$provience”, userid: “$userid”}}}, {$group: {_id: {country: “​$_id.country”, provience: “​$_id.provience”}, count: {​$sum:1}}}, {$project: {country: “$_id.country”, provicnce: “$_id.provience”, count: 1, _id: 0}} )

4.2. $project

​ 用来把前面group的字段重新命名输出,只要是针对分组的那个字段,其它的字段在分组时就可以自定义。

db.my_stu.aggregate( {$group: {_id: null, count: {$sum: 1}, mean_age: {​$avg: “​$age”}}}, {​$project: {gender: “$_id”, count: “​$count”, mean_age: 1, _id: 0}} ) # 前面分组基本不变,主要就是后面同样等级的 $project, 把$_id的键变成了gender,后面的就可以是这样操作,也可以使用0、1的投影操作。

4.3. $match

用于过滤数据,只输出符合条件的文档 (match是 管道命令,能将结果交给后一个管道,但是find不可以)

例1:查询年龄大于20的学生

例2:查询年龄大于等于18的男生、女生人数

例3: 年龄大于20或是家乡在蒙古或大理,再分组

​ Tips:一定要注意,这里因为显示的问题,==一些_id以及$符号前面加了一个转义符号\==,直接复制这去运行时一定要删掉才会成功。

4.4. $sort ​$limit $skip

​ $sort:将输入文档排序后输出

例1:按年龄分组,再根据各组人数降序排列

Tips:sort排序的时候是要指定排序的字段的,然后==-1是降序,1是升序==。

​ $limit $skip

db.my_stu.aggregate({$limit: 2}) # 跟前面的limit效果一样,就是只看两个 db.my_stu.aggregate({$skip: 2}) # 同上,跳过两个,显示剩余的

例:年龄升序排列,取第3条数据

4.5. $unwind

​ 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值 ​语法: db.集合名称.aggregate({$unwind: "$字段名称"})

#先插一条数据 db.t1.insert({_id:1, item: “t-shirt”, size: [“S”, “M”, “L”]}) db.t1.aggregate({$unwind: “$size”}) # 得到3条数据,就把字段size分开,成为3条数据

db.t1.insert({user: “Alex”, tags: [“c++”, “python”, “java”]}) # 如何知道这条数据 tags的长度呢

# 先在数据库里匹配到这条数据,然后用$unwind拆开,最后再通过上面null分组,求$sum

​ Ps:在使用unwind时,比如使用的字段是tags,而match匹配到的还有其他的Alex数据,然而它们有一些是没有tags这个字段的,那么在使用unwind后,它们会被丢弃,为了保留这些数据,得加一些

db.t1.ahhregate( {unwind: {path: “$字段名称”, preserveNullAndEmptyArrays:true}} ) # 这是固定写法

五、索引

db.t1.find({name: “test99999”}) db.t1.find({name: “test99999”}).explain(“executionStats”) # 就可以查看到执行时间


# 在默认情况下,索引字段的值可以相同 db.t1.ensureIndex({name: 1}, {unique: true}) # 加一个unique约束,那么所有的name的值就必须是唯一的,故可以使用数据库建立关键字段的唯一索引进行去重。

六、数据的备份与恢复

备份:

mongodump -h dbhost -d dbname -o dbdirectory

-h 服务器地址,也可指定端口号 # 本机时就可以不给 -d 需要备份的数据库名称 -o 备份的数据库存放位置,此目录中存放着备份出来的数据 例:mongodump -h 192.168.196.128:27017 -d test1 -o /home/

恢复:

mongorestore -h dbhost -d dbname –dir dbdirectory

-h 服务器地址 -d 需要恢复的数据库实例 –dir 备份数据所在位置 例:mongorestore -h 192.1468.196.128:27017 -d mytest01 –dir /home/mytest01

七、Python交互

更多的使用看这里

from pymongo import MongoClient

client = MongoClient(host="127.0.0.1", port=27017)
collection = client['mytest01']['t1']
datas = collection.find()   
# 得到的是所有的数据,为一个游标对象,可去循环获取

# 插入一条数据
collection.insert({"name": "张三丰", "age": 18})
# 插入多条数据,以一个列表的形式
data = [{"name": "test{}".format(i)} for i in range(10)]
collection.insert_many(data)
# 其它的就还是自己去菜鸟教程看

这里面出现的有趣的错误

例2:查询年龄大于等于18的男生、女生人数

例3: 年龄大于20或是家乡在蒙古或大理,再分组

Ps:一定要注意,这里为了美观,一些 _id 前面加了一个转义符号 \ ,直接复制这去运行时一定要删掉才会成功。