安装
- 在线安装:
sudo apt-get -y mongodb-org
- deb源码安装:
sudo dpkg -i package.deb
- 源码安装
tar -zxvf xxxx.taz
sudo mv -r xxxx /usr/local/mongodb
sudo vim .bashrc
- export PATH=/usr/local/mongodb/bin:$PATH
服务启动停止
- 默认端口:27017
- 配置文件:/etc/mongod.conf
- 默认日志:/var/log/mongodb/mongod.log
- 查看状态:
ps aux|grep mongod
- 查看配置:
gerp -v '#' /etc/mongod.conf
- 强杀:
ps aux|grep mongod
查看进程号,然后sudo kill 进程号
测试启动停止
sudo service mongod start
sudo service mongod stop
sudo service mongod restart
生产启动停止
参数说明
- sudo mongod 启动时,数据默认存在/data/db下,文件需要手动创建
- --dbpath:数据存放路经 ,使用:sudo mongod --dbpath=/home/data/aaaa
- --logpath:日志路径
- --append或--logappend:设置日志写入行为为追加
- --fork或-fork:开启新的进程运行mongodb服务
- --f或者-f:配置文件路径 sudo mongod -f /aa/mongo.conf
- --auth:权限认证方式启动
自定义配置文件
dbpath=/home/zhangyu/mymongo/db
logpath=/home/zhangyu/mymongo/mymongo.log
logappend=true
fork=true
客户端启动停止
- 打开:
mongo
- 退出:control+c 或者
exit
数据库操作
- 查看当前数据库:
db
(默认就是test数据库) - 查看所有磁盘上的库(内存中的不算):
show dbs
或者show database
- 切换数据库:
use 数据库名
- 删除当前所在数据库:
db.dropDatabase()
集和操作
- 查看集和列表:
show collections
- 创建集和:
db.createCollection("集和名",{capped:true,size:10})
- 两个判断集和属性的方法:
db.集合名.isCapped
- iscapped==true时,表示此集合设置上限
- size设置小于256时,系统自动分配256,大于256时,才是用户设置的
- 插入数据:
db.集合名.insert({"name":"chai","age":"18"})
- 查找集和中的数据:
db.集合名.find()
- 集合固定大小后,查询快,插入值不允许被修改
- 删除集合:
db.集合名.drop()
数据类型
- object ID:主键
- String:字符串
- Boolean:true和false
- Integer:整数
- Double:浮点
- Array:数组
- Object:mongodb中的一条数据
- Timestamp:时间戳
- Date:UNIX时间格式
- Null:存储null值
- ⚠️objectid在集合内唯一
增删改查
插
- 批量插入:
db.集合名.insert([{},{}])
- 保存:
- 先校验objid,如果有则检查数据,数据一致就跳过,否则覆盖掉原来数据,如果id也没有,则新增一条数据:
db.集合名.save({_id:"aaa",name:"fuck"})
- 先校验objid,如果有则检查数据,数据一致就跳过,否则覆盖掉原来数据,如果id也没有,则新增一条数据:
查
db.集合名.find()
db.集合名.findOne()
db.集和名.find().pretty() //美化输出
运算符
- $lt:小于
- $lte:小于等于
- $gt:大于
- $gte:大于等于
- $ne:不等于
例如:查询大于18岁的所有学生
db.stu.find({age:{$gt:18}})
条件运算
- 和:以下两种都可以:
db.stu.find({age:{$gt:18}},gender:true)
db.stu.find($and[{age:{$gt:18}},{gender:true}])
- 或:和上述内容一样,关键字改成
or
即可
范围运算
- $in:在范围中:
db.stu.find({age:{$in:[18,19,20]}})
- $nin:查找不在其中的,和上面用法一样
正则
查询开头是“黄”的数据:
db.stu.find({name:{$regex:'^黄'}})
自定义查询
db.stu.find({$where:
function(){
this.age > 18
}
)
查询结果操作
- limit:限制查询条数
db.stu.find().limit(1)
- skip:跳过查询结果中的n条
db.stu.find().skip(1) //跳过一条查询结果
skip和limit配合可制作分页逻辑:
db.stu.find().skip(0).limit(10) // 第一页
db.stu.find().skip(10).limit(10) // 第二页
⚠️:skip和limit配合时候不论谁先写前面,都是skip先起效果
- 投影:在查询结果里只显示想看的字段
db.stu.find({},{name:1,age:1}) //不想看的不写即可,不能写xxx:0【objid可以写0】
- 排序
db.stu.find().sort({age:1})//1升序,-1降序
- 统计个数
db.stu.find().count()
db.stu.count()
db.stu.count({age:19})
db.stu.find({age:18}).count()
- 去重
db.stu.distinct("hometown") // 不重复的展示出乡村列表
db.stu.distinct("hometown",{age:18}) //查询结果去重
改
基础格式:
//query:查询条件
//update:修改内容
//muti:false:只更新第一条(默认),否则更新全部
db.stu.update({query},{update},{muti:boolean})
实例:
# 把一班所有的数据的饭全改为屎,且覆盖整条文档
db.stu.update({class:"1"},{eat:"shit"})
# 只会把一班对应的吃这个key修改,该条文档其他值不变
db.stu.update({class:"1"},{$set:{eat:"shit"}})
# 更新多条,注意:用muti时必须使用$set
db.stu.update({class:"1"},{$set{eat:"shit"}},{muti:true})
upsert操作
功能为:找到就修改,找不到就新增一条数据
db.stu.update({name:"laotou"},{$set{eat:"shit"}},{upsert:true})
删除
# 删除全部符合条件的
db.stu.remove({name:"laotou"},{justOne:false})
聚合操作
使用aggregate函数,常用的是group管道
# 每一个大括号都是一个管道
db.stu.aggregate({},{},...)
- _id:使用键进行分组
# 使用gender的值将数据分组 db.stu.aggregate({$group:{_id:"$gender"}}) # 根据gender分组后,显示数据里增加一个计数器显示,表达式为累加,每次+1,⚠️:不能是0 db.stu.aggregate({$group:{_id:"$gender",counter:{$sum:1}}})
⚠️:除了_id,其他的键都可以自己定义,然后被显示在结果中
- 分组求和(和上面的是一个体系的):
# 注意sum的值不是1了,而是求和的依据是哪个key db.stu.aggregate({$group:{_id:"$gender",age_sum:{$sum:"$age"}}})
- 求平均数
# 和求和一个意思 db.stu.aggregate({$group:{_id:"$gender",avg_age:{$avg:"$age"}}})
- 在分组结果里构建一个数据组
db.stu.aggregate({$group:{_id:"$gender",name_list:{$push:"$name"}}})
- 常用表达式总结
- sum:1每次+1
- $avg:平均值
- $max:获取最大值
- $push:在结果集中,插入值到数组中
- 其他骚操作:不分组但使用分组函数
# 不分组,但计算总数量 db.stu.aggregte({$group:{_id:null,counter:{$sum:1}}})
match管道
用法非常简单
# 找出18岁的人,进行性别分组
db.stu.aggregate({$match:{age:18}},{$group:{_id:"$gender"}})
# 模糊匹配"黄",然后再分组
db.stu.aggregate({$match:{name:/黄/}},{$group:{_id:"$gender"}})
project管道
相当于投影(select key1 key2 .....)
# ⚠️投影的key可以是分组时构造出的新名字哟!!!
db.stu.aggregate({$group:{_id:"gender",avg_age:{$avg:"$age"}}},{$project:{avg_age:1}})
sort管道
# 1:升序,-1:降序
db.stu.aggregate({$sort:{age:1}})
limit和skip管道
⚠️:由于管道的执行有先后顺序,所以这里的limt和skip不能用来分页,分完就乱套了,当然如果想强行装逼也可以用。
# 先找到10条,再跳过两条
db.stu.aggregate({$limt:10},{$skip:2})
拆分管道
如果有的字段对应一个数组,可以根据这个数组将一条数据拆分开
# 根据size拆分,不展示异常数据
db.stu.aggregate({$unwind:"$size"})
# 根据size拆分,并且展示没有size属性和有属性但没有值的数据
db.stu.aggregate({$unwind:{path:"$size",preserveNullAndEmptyArrays:true}})
索引
⚠️查询频繁的时候需要使用索引,增删改频繁时不要用索引
- 简单创建:
# 1升序,-1降序
db.集合名.ensureIndex({属性:1})
- 唯一索引创建
# 之后num对应的value不能再有相同的值了
db.stu.ensureIndex({num:1},{unique:true})
- 创建符合索引
db.集合名.ensureIndex({属性:1,卡卡卡:1})
- TIPS
- 创建10000条测试数据:
for(int i = 0;i<10000;i++)> {db.stu.insert({name:'test'+i,age:i})}
- 展示某数据执行的详细信息
db.find({age:9999}).explain("executionStats")
- 获取索引
db.stu.getIndexes()
- 删除索引
# 利用属性名
db.stu.dropIndex({age:1})
# 利用索引名
db.stu.dropIndex('age_1')
权限管理
mongodb默认没有设置管理员,需要手动添加
- 开启验证
在mongo.conf中添加auth=true
- 添加账号
⚠️:账号创建在哪个数据库中,就只能登陆哪个数据库
⚠️:超管只能创建在admnin数据库里
- 超管
# 使用超管
use admin
# 创建用户
db.createUser({user:"zhangyu",pwd:"123456",roles:['root']})
# 登陆
db.auth("zhangyu","123456")
- 创建普通用户
db.createUser({user:"zhangyu",pwd:"123456",roles:['readWrite']})
show users # 查看这个库里的用户账号
- 将所有账号都创建在admin里,并且统一管理
db.createUser({user:"zhangyu",pwd:"123456",roles:[{db:"库1",role:"read"},{db:"库2",role:"readWrite"}]})
- 删除用户(必须登录用户admin)
db.dropUser("zhangyu")
mongodb与python交互
登录
pip3 install pymongo
- 普通登录
from pymongo import MongoClient
client = MongoClient('120.1.1.1',27017)
collection = client[db名][集和名]
- 认证登录
# 认证方式1(不推荐,但仍然可用)
from urllib.parse import quote_plus
user = "zhangyu"
pass = "123456"
host = "129.3.3.4"
port = "27017"
# quote可以对字符串进行编码
uri = "mongodb://%s:%s@%s" % (quote_plus(user),quote_plus(password),host)
client = MongoClient(uri,port=port)
collection = client.db名.集和名
# 认证方式2(推荐)
db=client["admin"]
db.authenticate("zhangyu","123456")
collection = client["库"]["集和"]
集和操作
插入
# 单条插入
col.insert({username:"zhangyu"})
# 多条插入
col.insert([{username:"zhangyu"},{username:"zhangyu2"}])
查询
# 条件查询
for data in collection.find({条件})
print(data)
# 查询一条
collection.find_one()
更新
- 覆盖更新
# 第一个为查询条件,第二个为更新数据
col.update({"class":"zhangyu"},{"age":"18"})
- 按key更新
# 按key更新一条
col.update({},{"$set":{"id":"dddd"}})
# 按key更新多条
col.update({},{"$set":{"id":"dddd"}},muti=True)
# upsert操作
col.update({"查询的key":"查询的value"},{"$set":{"id":"dddd"}},upsert=True)
删除
- 删除单条
col.delete_one({"name":"zhangyu"})
- 删除多条
col.delete_many({"gender":"1"})