首先如果没有docker就先下载安装docker
docker search mongodb # 搜索mongodb镜像
docker pull mongo:latest # 安装mongodb最新版本, 也可以指定版本
docker images # 查看本地已经拉取的镜像
docker run -itd --name mongo -p 27017:27017 mongo --auth # 运行mongo容器, -p指定端口映射, --auth需要密码才能访问容器服务
docker ps # 查看正在运行的容器信息
# ### 开启用户验证, 开启验证之后游客就只能靠边站了(游客只能玩test测试库), 每次进mongodb都需要验证
exit # 退出容器
docker exec -it mongo /bin/bash # 进入容器
apt-get update # 更新源
apt-get install vim # 安装vim
# 修改 mongo 配置文件
vim /etc/mongod.conf.orig
配置文件中,加入以下配置,注意authorization前面要加空格,参考其他配置项就能发现
security:
authorization: enabled
重启mongodb
mongod -f /mongodb/conf/mongo.conf --shutdown
mongod -f /mongodb/conf/mongo.conf
# 给mongodb创建用户
$ docker exec -it mongo mongo admin # 后面的mongo admin是进入容器并执行的命令, 相当于进入容器,并执行此命令
# 当然上述操作可以分两步操作
$ docker exec -it mongo /bin/bash # 进入mongo容器
/# mongo admin # 以授权模式进入mongo ,创建了用户之后,都用授权模式进入
# 然后正式创建 userAdminAnyDatabase 用户
# 创建一个名为 root,密码为 123 的用户。
> db.createUser({ user:'myroot',pwd:'123',roles:[{ role:'userAdminAnyDatabase', db: 'admin'},{其他权限字典,可添加多个,也可只要一个}]});
# 尝试使用上面创建的用户信息进行连接。返回1则代表认证成功
> db.auth('root', '123')
# exit # 退出mongo
# docker exec -it mongo /bin/bash # 进入容器, mongo是容器名 , 或者也可以使用容器id
# mongo admin # 以授权模式进入mongodb的admin库中 (即需要身份认证才能操作数据库的) , 若用非授权模式启动, 则直接mongo就行了
如果不加admin, 则默认进入一个test库, 在这个库中也不能进行权限验证
# db.auth('myroot', '123') # 认证身份, 返回1则代表认证成功
用户权限:
一,掌握权限,理解下面4条基本上就差不多
1. mongodb是没有默认管理员账号,所以要先添加管理员账号,在开启权限认证。
2. 切换到admin数据库,添加的账号才是管理员账号。
3. 用户只能在用户所在数据库登录(也就是进行身份验证db.auth(...)),包括管理员账号。
4. mongo的用户是以数据库为单位来建立的,每个数据库有自己的管理员。
5. 管理员可以管理所有数据库,但是不能直接管理其他数据库,要先在admin数据库认证后才可以(添加root超级权限)。
注:帐号是跟着库走的,所以在指定库里授权,必须也在指定库里验证
二 用户权限说明
Read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。不能在其他数据库中建数据集合
root:只在admin数据库中可用。超级账号,超级权限,可以删除其他用户(删除用户的时候只能在admin数据库下删),而且root用户还能在其他数据库中建数据集合
# 简单点吧, 你如果是dbAdminAnyDatabase用户, 你就可以创建普通用户, 并且给普通用户对于某个或某些数据库的读/写权限
首先需要 use admin
验证身份 db.auth('myroot', '123') # 就相当于用myroot这个用户登录mongodb
use db1 # 创建db1数据库, 并且选择这个数据库
db.createCollection('article') # 创建article数据集合
会发现报错 not authorized on db1 to execute command # 没有权限执行创建数据集合的命令
回到admin权限库 use admin
db.grantRolesToUser("myroot", [{role: "root", db: "admin"}]) # 给myroot这个用户添加对于admin权限管理库的超级管理员(root)权限
添加了之后就可以横行无阻了, 就可以去其他数据库中肆意妄为了
# 撤销角色权限, 比如说 dbAdminAnyDatabase 用户去掉自己的root身份 db.revokeRolesFromUser("myroot", [{role: "root", db: "admin"}])
# 撤销自己的root身份
# 授予角色权限, 上面已经提到了 db.grantRolesToUser("myroot", [{role: "root", db: "admin"}])
# 创建普通用户 db.createUser({ user:'chen',pwd:'111',roles:[{ role:'readWrite', db: 'db1'}]});
# 用户chen对于db1数据库有读写权限, 对于其他数据库没有任何权限
# ### 注意 : 创建普通用户得去到对应的库下面创建, 这样创建的用户才能管理这个库
> db.system.users.find().pretty() 或者使用 > db.system.users.find() # 在admin库下查看全局所有用户
show users # 查看当前库下的用户
# 删除用户 :
> db.system.users.remove({_id:"XXX.XXX"}) # 根据id删除用户
> db.system.users.remove({user:"XXXXXX"}) # 根据用户名删除用户
# 更改密码 : db.changeUserPassword("myroot", "666") # 将myroot用户的密码改为666, 当然事先你得用myroot用户登录
# 登录mongodb : 一般用mongo admin直接进入admin库下,然后进行身份验证就行了, 或者 mongo -u myroot -p 123 "admin"
远程登录 mongo -host 192.168.3.17 --port 27017 -u myroot -p 123 "admin"
# ### MongoDB常用命令
> show dbs #显示数据库列表
> show collections #显示当前数据库中的集合(类似关系数据库中的表)
> show users #显示用户
> use <db name> #切换当前数据库,如果数据库不存在则创建数据库。
> db.help() #显示数据库操作命令,里面有很多的命令
> db.foo.help() #显示集合操作命令,同样有很多的命令,foo指的是当前数据库下,一个叫foo的集合,并非真正意义上的命令
> db.foo.find() #对于当前数据库中的foo集合进行数据查找(由于没有条件,会列出所有数据)
> db.foo.find( { a : 1 } ) #对于当前数据库中的foo集合进行查找,条件是数据中有一个属性叫a,且a的值为1
MongoDB没有创建数据库的命令,但有类似的命令。 如:如果你想创建一个“myTest”的数据库,先运行use
myTest命令,之后就做一些操作(如:db.createCollection(‘user’)),这样就可以创建一个名叫“myTest”的数据库。
其他命令
> db.dropDatabase() #删除当前使用数据库
> db.cloneDatabase("127.0.0.1") #将指定机器上的数据库的数据克隆到当前数据库
> db.copyDatabase("mydb", "temp", "127.0.0.1") #将本机的mydb的数据复制到temp数据库中
> db.repairDatabase() #修复当前数据库
> db.getName() #查看当前使用的数据库,也可以直接用db
> db.stats() #显示当前db状态
> db.version() #当前db版本
> db.getMongo() #查看当前db的链接机器地址
> db.serverStatus() #查看数据库服务器的状态
查看分片结果:
db.printShardingStatus()
测试:向test数据库的user表中添加10w条数据:
use test
for(var i=0;i<100000;i++){
db.user.insert({"name":"test"+i,"age":i});
}
# ### 登录命令
# ### 登录
mongo -uroot -p123 admin # 方法一
mongo admin 快捷进入mongo的admin权限库 然后 db.auth('root', '123') # 方法二
mongo # 进去之后 use admin 然后 db.auth('root', '123') # 方法三
# ### mongodb的三个结构: 数据库db/数据集(集合)collection/文档xxx, 分别对应着mysql中的数据库/数据表/数据记录
# ### 数据库相关操作
show dbs # 显示所有数据库
use db1 # 使用db1数据库,如果数据库中没数据,则该数据库也就不存在
db.stats() # 显示当前数据库的各种信息
db.dropDatabase() # 删除当前数据库, 包括数据库中的数据集
db # 显示当前所在的数据库
# ### 数据集相关操作
show collections # 显示当前库中所有数据集
db.createCollection("user") # 创建user数据集
db.users.renameCollection("staff") # 将user数据集改名为staff
db.staff.drop() # 删除staff数据集
# ### 文档(数据)相关操作
db.article.insert( {'title': '博客1','content': '开始写博客'} ); # 往article数据集中插入一条数据, 就相当于给insert函数传参一个字典,
# 其中键可以不加引号,会自动识别, 单双引号都可以用
db.article.find() # 显示article数据集中所有文档
for(var i = 3; i <=10; i++ ) { # for循环插入多个文档, 每条数据的字段不相同也能插入,这就是mongodb的柔软性
db.article.insert({
title: "我的第" + i + "篇博客"
});
}
db.article.count() # 查看article数据集有多少条数据
db.article.remove({}) # 删除article数据集中所有文档
# ### find语法
db.数据集名.find({"字段名":"条件"})
$gte, $gt, $lte, $lt # 大于等于, 大于, 小于等于, 小于
$eq, $ne # 等于, 不等于
正则表达式:/k/, /^k/ # 值中包含k, 值以k开头
# ### 注意, 正则表达式两边不要用引号包起来,会识别不了
db.[collection_name].distinct("field_name"); # 取出这个字段并排序, 结果就是里面有多个字段的数组
use komablog;
db.posts.remove({});
测试 :
use komablog;
db.posts.remove({});
db.posts.insert({title:"怪物猎人世界评测","rank":2,"tag":"game"});
db.posts.insert({title:"纸片马里奥试玩体验","rank":1,"tag":"game"});
db.posts.insert({title:"Utunbu16LTS的安装","rank":3,"tag":"it"});
db.posts.find({"tag": "game"}); # 取出tag是game的文档
db.posts.find({"rank": {$gte: 2}}); # 取出rank 大于等于2的文档
db.posts.find({"title": /马/}); # 取出title中包含'马'的
db.posts.find({"title": /^U/}); # 取出以'U'开头的
db.posts.distinct("tag"); # 取出tag字段的所有值,(自动去重并排序) 结果 : ["game", "tag"]
db.[collection_name].find({筛选条件}, {field1: true, field2: 1}) # 第二个字典里可以填写想/不要哪些字段
db.posts.find();
db.posts.find({"title": /u/, "rank":{$gte:5} }); # 相当于与, 找到两个条件同时成立的文档
db.posts.find({$or: [{"title": /u/}, {"rank":{$gte:4}}] }); # 或
db.posts.find({"rank": {$in: [3,4]} }); # rank字段值在[3, 4]中选
db.posts.insert({ "title":"惊!骑士发生重大交易", "istop": false }); # 添加一条新文档, 有一个新的字段istop
db.posts.find({"istop": {$exists: true} }); # 找到包含istop这个字段的文档, 结果就是刚刚我们插入的那条数据
db.posts.find({"tag": "game"},{title:true,rank:1}); # 取出tag是game的title字段和rank字段, 其中true和1是等价的,都代表true
而false和0也是等价的,都代表不取这个字段, 其实每次取默认都取_id字段, 所以可以用_id : 0来不取_id
sort() # 排序
limit() # 取出多少
skip() # 跳过多少再取
db.posts.find();
db.posts.find({}, {_id:0}).sort({rank:1}); # 按照rank字段进行升序排序
db.posts.find({}, {_id:0}).sort({rank:-1}); # 按照rank字段进行降序排序
db.posts.find({}, {_id:0}).limit(3);
db.posts.find({}, {_id:0}).sort({rank:-1}).limit(3);
db.posts.findOne({}, {_id:0}); # findOne只取一个,相当于后面加.limit(1)
db.posts.find({}, {_id:0}).limit(3); # 取前三个
db.posts.find({}, {_id:0}).skip(3).limit(3); # 跳过前三个再取三个
update(<filter>, <update>, <options>) # 第一个参数为筛选条件, 第二个为更新选项, 第三个为其他选项
$set # 修改或新增, 有这个字段就更新, 没有这个字段就添加 , 不加$set就是直接移除原有字段, 变成新字段了
update命令参考官网 https://docs.mongodb.com/manual/reference/method/db.collection.update
use komablog;
db.posts.findOne({"title":"怪物猎人世界评测"});
db.posts.update({"title":"怪物猎人世界评测"}, {$set: {"rank": 10} });
db.posts.find();
db.posts.update({"title":"怪物猎人世界评测"}, {"rank": 99}); # 将title是怪物猎人的文档更新为只剩'rank' : 99这一个字段
db.posts.find();
db.posts.update({"tag":"it"}, {$set: {"rank": 50}}); # 将tag为it的文档的rank更新为50,默认只更新一条
db.posts.find();
db.posts.update({"tag":"it"}, {$set: {"rank": 60}}, {multi: true}); # multi: true指定更新所有符合调价你的文档
db.posts.find();
$inc # 递加, increase
$mul # 相乘 multiply
$rename # 改名
$set # 新增or修改
$unset # 字段删除
$ mongo
use komablog;
db.posts.find({title:"纸片马里奥试玩体验"}, {_id:0});
db.posts.update({title:"纸片马里奥试玩体验"}, {$inc: {rank: 1}}); # 原来rank的基础上加1
db.posts.update({title:"纸片马里奥试玩体验"}, {$mul: {rank: 2}}); # 原来rank的基础上乘2
db.posts.update({title:"纸片马里奥试玩体验"}, {$rename: {"rank": "score"}}); # 将rank字段改名为score
db.posts.update({title:"纸片马里奥试玩体验"}, {$set: {"istop": true}}); # 新增字段istop: true
db.posts.update({title:"纸片马里奥试玩体验"}, {$unset: {"istop": true}}); # 删掉字段istop: true
db.posts.find({title:"纸片马里奥试玩体验"}, {_id:0});
upsert : true # 相对于文档(记录)有则更新,无则新增 ; 注意,之前那个$set是相对于字段的修改或新增, 需要区分一下
# 默认为false
.remove() # 条件删除数据(文档)
$ mongo
use komablog;
db.posts.find({}, {_id:0});
db.posts.update({title:"其实创造比大志好玩"}, {title:"其实创造比大志好玩", "rank":5,"tag":"game"}); # 没找到title为这个的数据,无法直接更新
db.posts.find({}, {_id:0});
db.posts.update({title:"其实创造比大志好玩"}, {title:"其实创造比大志好玩", "rank":5,"tag":"game"}, {upsert:true});
# 有则更新,无则新增,所以这里能够更新
db.posts.remove({title:"其实创造比大志好玩"});
db.posts.find({}, {_id:0});
# ### 数据集的索引
db.posts.getIndexes() # 查看当前数据集的索引
createIndex({...}, {...}) # 创建索引, 跟条件(创建什么样的索引?主键/普通索引等等), 创建索引为了方便查找
dropIndex({...}) # 删除索引
$ mongo
use komablog;
db.posts.getIndexes();
db.posts.createIndex({rank:-1}); # 以rank字段降序创建一个索引
db.posts.dropIndex({rank:-1}); # 删除刚刚创建的索引
db.posts.createIndex({title:1}, {unique:true}); # 创建一个以title字段升序的 唯一 索引
db.posts.find({}, {_id:0});
db.posts.insert({title:"怪物猎人世界评测"});
# title是唯一索引,并且值已经有怪物猎人了,再插入同样的会报错,duplicate key error collection(重复键错误数据集)
# 当然你如果插入一条没有title字段的文档, 也会报错, 错误原因是主键title不能为null
> db.posts.getIndexes();
[
{
"v" : 2,
"key" : {
"_id" : 1 # 只有_id这一个索引字段
},
"name" : "_id_", # 这是mongodb的默认索引
"ns" : "komablog.posts"
}
]
# ### 备份与恢复
mongodump # 备份
mongorestore # 恢复
# 参考博客
mongodump -uroot -p123 --authenticationDatabase admin -d komablog # 备份, 在mongodb外边执行的
# 其中--authenticationDatabase admin指的是在admin权限库中验证-u和-p带的用户名和密码, 作为游客的话就不认证
# -d 指定备份的数据库; -h 指明数据库宿主机的IP ; -c 指明collection数据集的名字; -f 指明要导出那些列(字段)
# -o 指明到要导出的文件名,默认为dump ; -q 指明导出数据的过滤条件 ; --type 指定文件类型
mongorestore -uroot -p123 --authenticationDatabase admin --drop # 恢复, 在mongodb外边执行的
# 上面有的参数就不说了, 还有一个新参数 --drop 插入之前先删除原有的(就相当于重写)
# --headerline 指明第一行是列名,不需要导入。
# -j 同时运行的插入操作数(默认为1),并行
# 备份完了删数据集, 然后出来ls看一下备份文件, 然后恢复, 进去mongodb看数据又回来了
# ### 与python的交互
pip install pymongo
from pymongo import *
client = MongoClient('mongodb://127.0.0.1:27017') # 无安全认证的mongo连接
client = MongoClient('mongodb://用户名:密码@127.0.0.1:27017/验证数据库') # 有安全认证的mongo连接
# pymongo有两个类比较重要
# 1 database类,用来获取数据库
db = client.db1 # 指定连接db1数据库
# 2 collection类
主要方法:
insert_one insert_many update_one update_many delete_one delete_many find_one find
article_obj = db1.article # 获取article集合对象,接下来就可以操作一波了
s1_id = article_obj.insert_one({'name': '张三丰', 'age': 61}).inserted_id # 后面加个.insert_id, 可以返回插入数据的id, 当然也可以不加.insert_id不看
print(s1_id)
article_obj.update_one({'name': '张三丰', 'age': 61}, {$set: {name: '张四丰'}})
# .sort() 排序, 升序用ASCENDINT, 降序用DESCENDING
# 错了 好像现在不能用ASCENDINT和DESCENDING,得用1和-1
res = article.find().sort([ ('rank',1),('tag',-1) ]) # 注意, 这里不是一个字典了,中间是逗号
# ### 实例
from pymongo import MongoClient
client = MongoClient('mongodb://root:123@106.53.21.61:27017/admin')
# 1 database类,获取数据库
db1 = client.komablog
posts_obj = db1.posts
# s1_id = posts_obj.insert_one({'name': '张三丰', 'age': 61}).inserted_id # 后面加个.insert_id, 可以返回插入数据的id,
# 当然也可以不加.insert_id不看
# print(s1_id)
# posts_obj.update_one({'name': '张三丰'}, {'$set': {'name': '张四丰'}})
# 其他操作都是按照方法来了,posts_obj就相当于在mongo中的db.posts
# res = posts_obj.find({'rank': {"$gte": 1}}).sort([('rank', 1), ('tag', -1)])
res = posts_obj.find().sort([('rank', 1), ('tag', -1)])
for i in res:
print(i)