MongoDB学习笔记,按照以下几项来记录一下:
一、MongoDB的安装
下面说一下在生产环境中CentOS上面的安装过程,同样也是适合在MacOS上面进行MongoDB的安装:
Step1:去https://www.mongodb.com/download-center/community官网上面找到对应的链接(https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.10.tgz)这里需要注意一下版本号,偶数代表了稳定的版本,可以放在生产环境中。

找到链接之后,我们就能够在CentOS中直接将文件给拉到本地。
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.10.tgz
Step 2:解压前面下载的文件夹,然后仔细看看里面的内容
tar -zxvf mongodb-linux-x86_64-4.0.10.tgz
cd ~/mongodb-linux-x86_64-4.0.10/bin
tree
通过tree命令我们就看到了bin文件夹下面的文件了,这里是有12个文件夹的。
.
├── bsondump
├── install_compass
├── mongo
├── mongod
├── mongodump
├── mongoexport
├── mongofiles
├── mongoimport
├── mongoreplay
├── mongorestore
├── mongos
├── mongostat
└── mongotop
下面对这些文件进行一个说明:
bsondump:导出bson的结构
mongo:客户端
mongod:服务端
mongodump:整体数据库的导出
mongoexport:导出易识识别的json文档或者csv文档
mongorestore:数据库的整体导入
mongos:路由器
Step3:将bin文件夹拷贝到/usr/local/mongodb下面去,并建立data文件夹和dblogs文件。data文件夹主要是存放我们的数据的,然后dblogs记录的就是我们的日志了。
cd ./bin
rsync -a bin /usr/local/mongodb
经过这个操作,我们就将bin文件夹给复制到了/usr/local/mongodb
cd /usr/local/mongodb
mkdir data
touch dblogs
Step4:开启一个服务
进入/usr/local/mongodb下面的bin文件夹,执行下面的命令:
--dbpath是执行数据库存放路径(默认是/data/db)
--fort是以Daemon(进程)的方式运行,要是采用了它,那么必须要制定 --logpath,也就是我们日志的路径。
./mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/dblogs --fork
要是你使用的的macOS的话,就需要注意一下要使用sudo的操作了,不然就会报错:
☁ bin ./mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/dblogs --fork
2019-09-15T11:05:01.959+0800 I STORAGE [main] Max cache overflow file size custom option: 0
about to fork child process, waiting until server is ready for connections.
forked process: 55406
ERROR: child process failed, exited with error number 1
To see additional information in this output, start without the "--fork" option.
sudo之后结果出现下面,就说明执行成功了
about to fork child process, waiting until server is ready for connections.
forked process: 20632
child process started successfully, parent exiting
然后我们看看进行的列表。
pstree -p | grep mongo
结果显示,我们有一个主进程mongod,然后后面还接上了很多个子进程。
|-mongod(20632)-+-{mongod}(20633)
| |-{mongod}(20634)
| |-{mongod}(20639)
| |-{mongod}(20640)
| |-{mongod}(20641)
| |-{mongod}(20642)
| |-{mongod}(20643)
| |-{mongod}(20644)
| |-{mongod}(20645)
| |-{mongod}(20646)
| |-{mongod}(20647)
| |-{mongod}(20648)
| |-{mongod}(20649)
| |-{mongod}(20650)
| |-{mongod}(20651)
| |-{mongod}(20652)
| |-{mongod}(20653)
| |-{mongod}(20654)
| |-{mongod}(20655)
| |-{mongod}(20656)
| |-{mongod}(20657)
| |-{mongod}(20658)
| `-{mongod}(20659)
要是我们需要开机就启动mongod的话,启动服务,我们就去/etc/rc.local进行修改,这个就是计算机启动偏后的一个脚本了。我们在这个文件中加入下面这个命令,开机的时候就能启动了。
/usr/local/mongodb/mongod --dapath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/dblogs --fork
我们这里是开启了mongo,要是关闭怎么操作呢,可以采用pkill、killal
l或者kill-2的方式去杀掉这个进程,但是不要用kill -9的方式去杀掉进程,因为这样杀掉了的话,服务会起不来了,要想起,就得删掉mongo.lock。
pkill mongod # killall mongod
Step5:启动客户端
/usr/local/mongodb/bin/mongo
二、MongoDB里面的基本概念
数据库(Database):数据库就是一个仓库,在仓库中可以存放集合。
集合(collection):集合里面可以存放文档。
文档(document):文档数据库中的最小单位,我们在文章数据库中操作的内容都是文档。

- 数据类型
Object ID: ⽂档ID ,每个⽂档都有⼀个属性, 为_id, 保证每个⽂档的唯⼀性。可以⾃⼰去设置_id插⼊⽂档,如果没有提供, 那么MongoDB为每个⽂档提供了⼀个独特的_id, 类型为objectID。是⼀个12字节的⼗六进制数: 前4个字节为当前时间戳,接下来3个字节的机器ID,接下来的2个字节中MongoDB的服务进程id,最后3个字节是简单的增量值
String: 字符串, 最常⽤, 必须是有效的UTF-8
Boolean: 存储⼀个布尔值, true或false,这里注意是小写的。对应于json里面的true or false
Integer: 整数可以是32位或64位, 这取决于服务器
Double: 存储浮点值 Arrays: 数组或列表, 多个值存储到⼀个键
Object: ⽤于嵌⼊式的⽂档, 即⼀个值为⼀个⽂档
Null: 存储Null值
Timestamp: 时间戳, 表示从1970-1-1到现在的总秒数
Date: 存储当前⽇期或时间的UNIX时间格式
三、MongoDB的基本操作
1、基本的指令
show dbs
show databases ---->显示当前所有的数据库,等价于show dbs
use 数据库名 ---->进入到指定的数据库中
show collections ---->显示数据库中所有的集合
db.collection.drop()
- 这里需要注意的是我们不用手动创建集合,第一次进行数据插入的时候,我们就集合会被自动的创建出来。
- 手动的创建集合
db.createCollection(name, options)
db.createCollection("stu", {capped:true, size:10}) #这里capped为true的时候,表示文档能到的上限的是size大小。
2、数据库的CRUD操作
下面的<collection>就代表了了集合的名字
(1)插入操作
db.<collection>.insert(doc)
e.g.
db.stu.insert({name:"tiger", age:18, gender:"male"})
db.<collection>.insertOne()
db.<collection>.insertMany()
db.<collection>.save()
(2)查询操作
db.<collection>.find()
-- find()用来查询集合汇总所有符合条件的文档
-- find()可以接收一个对象作为条件参数。{}表示查询集合汇总所有的文档。{属性:值}
-- find()返回的是一个数组
db.<collection>.findOne()
-- findone()用来查询集合中符合条件的第一个文档
-- findone()返回的是一个对象
db.<collection>.find({})的效果和db.<collection>.length()
查询所有结果的数量
> db.stu.find()
{ "_id" : ObjectId("5c861b97d5a265a5e2148ecd"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861e8cd5a265a5e2148ed1"), "name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true }
{ "_id" : ObjectId("5c861e99d5a265a5e2148ed2"), "name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
> db.stu.find({age:18})
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
> db.stu.findOne({age:18})
{
"_id" : ObjectId("5c861bbad5a265a5e2148ece"),
"name" : "黄蓉",
"hometown" : "桃花岛",
"age" : 18,
"gender" : false
}
- 比较运算符
等于: 默认是等于判断, 没有运算符
⼩于:$lt (less than)
⼩于等于:$lte (less than equal)
⼤于:$gt (greater than)
⼤于等于:$gte
不等:$ne
找年龄小于等于18岁的
> db.stu.find({age:{$lte:18}})
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e8cd5a265a5e2148ed1"), "name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
- 逻辑运算符
(1) and:在json中写多个条件即可 查询年龄⼤于或等于18, 并且性别为true的学⽣ db.stu.find({age:{$gte:18}, gender:true})
(2) or:使⽤$or, 值为数组, 数组中每个元素为json 查询年龄⼤于18, 或性别为false的学⽣ db.stu.find({$or:[{age:{$gt:18}}, {gender:false}]})
(3) 查询年龄⼤于18或性别为男⽣, 并且姓名是郭靖 db.stu.find({$or:[{age:{$gte:18}}, {gender:true}], name:'郭靖'})
> db.stu.find({age:{$gte:18}, gender:true})
{ "_id" : ObjectId("5c861b97d5a265a5e2148ecd"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861e99d5a265a5e2148ed2"), "name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
> db.stu.find({$or:[{age:{$gt:18}}, {gender:false}]})
{ "_id" : ObjectId("5c861b97d5a265a5e2148ecd"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861e99d5a265a5e2148ed2"), "name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true }
-
范围运算符
使⽤"$in", "$nin" 判断是否在某个范围内 查询年龄为18、 28的学⽣ db.stu.find({age:{$in:[18,28]}}) -
limit和skip
(1)⽅法limit(): ⽤于读取指定数量的⽂档 db.集合名称.find().limit(NUMBER) 查询2条学⽣信息 db.stu.find().limit(2)
(2)⽅法skip(): ⽤于跳过指定数量的⽂档 db.集合名称.find().skip(NUMBER) db.stu.find().skip(2)
(3)同时使用:db.stu.find().limit(4).skip(5) 或 db.stu.find().skip(5).limit(4)
> db.stu.find().skip(2)
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861e8cd5a265a5e2148ed1"), "name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true }
{ "_id" : ObjectId("5c861e99d5a265a5e2148ed2"), "name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
> db.stu.find().limit(3)
{ "_id" : ObjectId("5c861b97d5a265a5e2148ecd"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
> db.stu.find().skip(2).limit(3)
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861e8cd5a265a5e2148ed1"), "name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true }
- 投影
在查询到的返回结果中, 只选择必要的字段 db.集合名称.find({},{字段名称:1,...}) 参数为字段与值, 值为1表示显示, 值为0不显 特殊: 对于_id列默认是显示的, 如果不显示需要明确设置为0。
db.stu.find({},{_id:0,name:1,gender:1}) - 排序
⽅法sort(), ⽤于对 集进⾏排序 db.集合名称.find().sort({字段:1,...}) 参数1为升序排列 参数-1为降序排列 根据性别降序, 再根据年龄升序 db.stu.find().sort({gender:-1,age:1})
> db.stu.find().sort({age:1})
{ "_id" : ObjectId("5c861e8cd5a265a5e2148ed1"), "name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true }
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
{ "_id" : ObjectId("5c861b97d5a265a5e2148ecd"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861e99d5a265a5e2148ed2"), "name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true }
> db.stu.find().sort({age:-1})
{ "_id" : ObjectId("5c861e99d5a265a5e2148ed2"), "name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861b97d5a265a5e2148ecd"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
{ "_id" : ObjectId("5c861e8cd5a265a5e2148ed1"), "name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true }
> db.stu.find().sort({age:-1,gender:-1})
{ "_id" : ObjectId("5c861e99d5a265a5e2148ed2"), "name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true }
{ "_id" : ObjectId("5c861e77d5a265a5e2148ed0"), "name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true }
{ "_id" : ObjectId("5c861b97d5a265a5e2148ecd"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
{ "_id" : ObjectId("5c861eaad5a265a5e2148ed3"), "name" : "洪七公", "hometown" : "华山", "age" : 18, "gender" : true }
{ "_id" : ObjectId("5c861bbad5a265a5e2148ece"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e61d5a265a5e2148ecf"), "name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false }
{ "_id" : ObjectId("5c861e8cd5a265a5e2148ed1"), "name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true }
- 统计个数
⽅法count()⽤于统计结果集中⽂档条数
db.集合名称.find({条件}).count()
db.集合名称.count({条件})
db.stu.find({gender:true}).count()
db.stu.count({age:{$gt:20},gender:true})
> db.stu.count()
7
> db.stu.find({age:{$gt:18}}).count()
3
> db.stu.count({age:{$gt:18}})
3
- 消除重复
distinct()主要对数据进行一个去重的操作
db.集合名称.distinct('去重字段',{条件})
> db.stu.distinct('hometown',{age:{$gt:18}})
[ "蒙古", "桃花岛", "大理" ]
(3)修改操作
db.<collection>.update(查询条件,新对象)
--update()默认会使用新对象来替换旧对象,这样的房还是不是很好
--如果需要修改执行的属性,而不是替换需要,使用修改操作符
$set 可以用来修改文章中的指定属性
$unset可以用来删除文档中的指定属性
db.<collection>.updateMany()
db.<collection>.updateOne()
(4)删除操作
db.<collection>.remove()
--删除符合条件的所有的文档(默认情况下回删除多个),如果remove的第二个参数为True,则只会删除一个。如果只传递一个空对象作为参数,则会删除集合中的所有文档。
db.<collection>.deleteOne()
db.<collection>.deleteMany()
3、聚合操作
聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。
表示形式:db.collection.aggregate({管道:{表达式}})
- 常用管道
在mongodb中,⽂档处理完毕后, 通过管道进⾏下⼀次处理
$group: 将集合中的⽂档分组, 可⽤于统计结果
$match: 过滤数据, 只输出符合条件的⽂档
$project: 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
$unwind: 将数组类型的字段进⾏拆分
$sort: 将输⼊⽂档排序后输出
$limit: 限制聚合管道返回的⽂档数
$skip: 跳过指定数量的⽂档, 并返回余下的⽂档
这几个常用的命令中,group、match以及project是很重要的。 - 表达式
常⽤表达式:
$sum: 计算总和, $sum:1 表示以⼀倍计数
$avg: 计算平均值
$min: 获取最⼩值
$max: 获取最⼤值
$push: 在结果⽂档中插⼊值到⼀个数组中
$first: 根据资源⽂档的排序获取第⼀个⽂档数据
$last: 根据资源⽂档的排序获取最后⼀个⽂档数据
(1)$group
> db.stu.aggregate({$group:{_id:"$gender"}}) #没有统计任何的东西,注意¥符号
{ "_id" : false }
{ "_id" : true }
> db.stu.aggregate({$group:{_id:"$gender", count:{$sum:1} }})
{ "_id" : false, "count" : 2 }
{ "_id" : true, "count" : 5 }
# 对年龄进行一个平均
> db.stu.aggregate({$group:{_id:"$gender", count:{$sum:1}, age_avg:{$avg:"$age"}}})
{ "_id" : false, "count" : 2, "age_avg" : 18 }
{ "_id" : true, "count" : 5, "age_avg" : 27.8 }
> db.stu.aggregate({$group:{_id:"$hometown", mean_age:{$avg:"$age"}}})
{ "_id" : "华山", "mean_age" : 18 }
{ "_id" : "大理", "mean_age" : 30.5 }
{ "_id" : "桃花岛", "mean_age" : 29 }
{ "_id" : "蒙古", "mean_age" : 19 }
# 常用的group by null进行一个总的统计工作
> db.stu.aggregate({$group:{_id:null, counter:{$sum:1}, avg_age:{$avg:"$age"}}})
{ "_id" : null, "counter" : 7, "avg_age" : 25 }
注意点:
- $group对应的字典中有几个键,那么结果中就有几个键
- 分组一句需要放到_id后面
- 去不同搞得字段的值需要在字段名字前加上
gender'
(2)$project
前面已经说明了project的意思了,1表示我们要这个字段,0表示我们不要这个字段,用来修改输入输出的样子
> db.stu.aggregate({$group:{_id:"$gender", count:{$sum:1}, age_avg:{$avg:"$age"}}}, {$project:{_id:0, count:1, age_avg:1}})
{ "count" : 2, "age_avg" : 18 }
{ "count" : 5, "age_avg" : 27.8 }
(3)$match
这个命令也用的比较多,值输出符合条件的文档,辅助我们的管道命令。match是管道命令,能将结果交给后一个管道,但是find不可以。
我们要选择年龄大于20的学生,观察男性和女性有多少人。
一过滤、二分组、三投影。上一步的输出作为下一步的输入
> db.stu.aggregate({$match:{age:{$gt:20}}},{$group:{_id:"$gender", count:{$sum:1}}}, {$project:{_id:0,gender:"$_id",count:1}})
{ "count" : 2, "gender" : true }
> db.stu.aggregate({$match:{age:{$gte:18}}},{$group:{_id:"$gender", count:{$sum:1}}}, {$project:{_id:0,gender:"$_id",count:1}})
{ "count" : 2, "gender" : false }
{ "count" : 4, "gender" : true }
四、pymongo的操作
在Python里面去操作MongoDB,那么我们就需要安装一个Python的包--pymongo。安装直接用pip安装一下就好了,api的网站在http://api.mongodb.com/python/current/api/pymongo/index.html
pip install pymongo
然后锯条的操作过程如下所示:
import pymongo
# 1、首先是连接数据库服务器,获得客户端对象
client = pymongo.MongoClient('localhost', 27017)
#2、获取数据库的对象
db = mongo_client.myDB
#3、获取集合对象
col_obj = db.myCollection
参考资料:
1、https://www.bilibili.com/video/av10743361?from=search&seid=13704486801750678893
2、https://www.bilibili.com/video/av21989676?from=search&seid=13704486801750678893
网友评论