好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

MongoDB数据库的使用

name ‘ : ‘ guojing ‘ , ‘ gender ‘ : ‘ 男 ‘ } 集合 :类似于关系数据库中的表,储存多个文档,结构不固定,示例
{ ‘  name  ‘ : ‘  guojing  ‘ , ‘  gender  ‘ : ‘  男  ‘  }
{  ‘  name  ‘ : ‘  huangrong  ‘ , ‘  age  ‘ :18 }
{  ‘  book  ‘ : ‘  shuihuzhuan  ‘ , ‘  heros  ‘ : ‘  108  ‘ }

一、环境安装与运行

安装

sudo apt-get install mongodb

  配置文件为 /etc/mongodb.conf,默认端口号:27017

启动服务器

sudo service mongodb start   #相当于执行命令 sudo mongod --config /etc/mongod.conf 

关闭服务器

sudo service mongodb stop

重启服务器

sudo service mongodb restart  #  修改了配置文件/etc/mongodb.conf后,需要重启mongodb服务器让配置生效 

启动客户端

sudo mongo

二、数据库操作

查看当前数据库

db

查看所有数据库

show dbs

切换(或创建)数据库

use 数据库名

切换数据库,如果数据库不存在,当插入数据或创建集合时,会自动创建这个数据库

删除数据库

db.dropDatabase()

删除当前指向的数据库,如果不存在,则什么也不做

三、集合操作

创建

 db.createCollection(name[,options])
  #  name集合名称  
#  options可选,是一个用于指定集合配置的文档,其中capped参数默认不设置上限(false),若设置上限(true)则需要指定参数size,单位字节 
 #  不设置集合大小 
db.createCollection( "  stu  "  )
  #  设置集合大小 
db.createCollection( "  sub  " , { capped : true, size : 10 } )

查看当前数据库集合

show collections

删除集合

db.集合名.drop()

四、数据操作

插入

db.集合名.insert(文档) 或 db.集合名.insert([文档...])
# 如果不指定_id字段,则分配一个唯一的ObjectId;如果指定_id字段,且_id已经存在时,不做任何操作;如果一次性插入多条数据,以数组的方式传入文档
 #   不指定_id 
db.stu.insert({name: ‘  gj  ‘ ,gender:1 })

  #  指定_id 
s1={_id: ‘  20160101  ‘ ,name: ‘  hr  ‘  }
s1.gender = 0
db.stu.insert(s1) 

删除--(注意justOne参数)

db.集合名.remove(条件,{justone:<boolean>})  #参数  justOne默认false,删除多条 
 #   只删除匹配到的一条数据 
 db.stu.remove({gender:0},{justOne:true})

  #  删除所有 
db.stu.remove({})

修改--(注意$set以及multi参数)

db.集合名.update({条件},$操作符,{multi: <boolean>}])  #参数  multi只和$操作符一起使用,默认false,只修改一条数据,true表示修改多条数据 
 #   不使用操作符$set,修改整条文档 
db.stu.update({name: ‘  hr  ‘ },{name: ‘  mnc  ‘  })

  #使用  操作符$set指定属性修改 
db.stu.update({name: ‘  hr  ‘ },{$set:{name: ‘  hys  ‘  }})

  #multi参数和$set一起使用,修改多条文档 
db.stu.update({},{$set:{gender:0}},{multi:true})

保存

db.集合名.save(document) 
# 在手动插入_id字段时,如果_id已经存在,做全文档更新操作,其余均表示插入数据。
db.stu.save({_id: ‘  20160102  ‘ , ‘  name  ‘ : ‘  yk  ‘ ,gender:1 })
db.stu.save({_id:  ‘  20160102  ‘ , ‘  name  ‘ : ‘  wyk  ‘ })  #  对上述文档做修改 

查询

基本查询
db.集合名.find({条件文档})  #  查询所有 
db.集合名.findOne({条件文档})  #  只查询第一条 
db.集合名.find({条件文档}).pretty()  #  结果格式化输出 
比较运算符 等于:默认,没有运算符 小于: $lt 小于等于: $lte 大于:$gt 大于等于:$gte 不等于:$ne
 #  查询年龄大于等于18的学生 
db.stu.find({ "  age  " :{$gte:18}})
逻辑运算符 逻辑与:默认 逻辑或:$or
 #   查询年龄大于或等于18,并且性别为1的学生 
db.stu.find({ "  age  " :{$gte:18}, "  gender  " :1 })

  #  查询年龄大于18,或性别为0的学生 
db.stu.find({$ or :[{ "  age  " :{$gt:18}},{ "  gender  " :1 }]})

  #  查询年龄小于18或者大于20,性别为1的学生 
db.stu.find({$ or :[{ "  age  " :{$lt:18}},{ "  age  " :{$gt:20}}], "  gender  " :1})
范围运算符 在某个范围$in,后面接数组 不在某个范围$nin,后面接数组
 #  查询年龄18、20以及22岁的学生 
db.stu.find({ "  age  " :{$ in :[18,20,22 ]}})

  #  查询年龄不等于18或20的学生 
db.stu.find({ "  age  " :{$nin:[18,20]}})
正则表达式 使用/表达式/或者$regex
 #  查询姓黄的学生 
db.stu.find({ "  name  " :/^黄/ })
db.stu.find({  "  name  " :{$regex: "  ^黄  " }})
自定义查询 使用$where:function(){return 满足条件的数据表达式}------运算符使用js语法,比如逻辑与(&&),逻辑或(||)
 #  查询年龄18-22的学生 
db.stu.find({$where:function(){ return  this.age>18 && this.age<22 }})

  #  查询年龄小于18或者大于22的学生 
db.stu.find({$where:function(){ return  this.age<18 || this.age>22}})
投影 只显示部分字段
db.集合名.find({条件},{字段名:1,...})  #  1表示该字段显示,0不显示;_id列默认显示,不显示需要明确设置为0 
 #  查询姓名和年龄(显示_id) 
db.stu.find({},{name:1,gender:1 })

  #  查询姓名和年龄(不显示_id) 
db.stu.find({},{_id:0,name:1,gender:1})
skip 跳过指定数量的文档
db.集合名.find({条件}).skip(number)  #  number默认为0 
 #  查询从第3条开始的学生信息 
db.stu.find().skip(2)
limit 读取指定数量的文档
db.集合名.find({条件}).limit(number)  #  不写number参数,默认读取所有文档 
 #  读取3条学生信息 
db.stu.find().limit(3)
skip和limit合用 不区分先后顺序
 #  查询第5-9条学生信息 
db.stu.find().skip(4).limit(5)  #  相当于跳过4条数据,选5条 
sort 对结果集进行排序
db.集合名称.find({条件}).sort({字段:1,...})  #  1表示升序,-1表示降序 
 #  根据性别降序,再根据年龄升序 
db.stu.find().sort({ "  gender  " :-1, "  age  " :1})
count 对结果集中文档数目进行统计,返回整数
 db.集合名.find({条件}).count() 
或者 
db.集合名.count({条件}) 
 #  统计年龄大于20的男生人数 
db.stu.count({ "  age  " :{$gt:20}, "  gender  " :1})
distinct 对数据去重,返回的是一个列表
db.集合名.distinct( "  字段名  " ,{条件}) 

五、聚合(aggregate)

聚合主要用于计算数据,类似sql中的sum()、avg()

db.集合名.aggregate([{管道:{表达式}}...])

管道

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

表达式

处理输入文档并输出 语法:表达式:‘$字段名’ 常用表达式: $sum:计算总和,$sum:‘$字段‘表示求和,注意$sum:1表示计数, $avg:计算平均值 $min:获取最小值 $max:获取最大值 $push:在结果文档中插入值到一个数组中(以列表的方式显示字段值) $first:根据资源文档的排序获取第一个文档数据 $last:根据资源文档的排序获取最后一个文档数据

$group

文档分组,用于统计结果 _id表示分组的依据,使用某个字段的格式为‘$字段‘
 #   统计男、女生人数 
db.stu.aggregate([{$group:{ "  _id  " : ‘  gender  ‘ , "  couter  " :{$sum:1 }}}])
  #  结果文档中显示_id和counter的值 
_id按照null分组,会将集合中所有文档分为一组
 #   求学生总人数和平均年龄 
db.stu.aggregate([{$group:{_id:null,counter:{$sum:1},average_age:{$avg: "  $age  " }}}])
使用$$ROOT可以将文档内容加入到结果集的数组中
 #  统计男、女生信息 
db.stu.aggregate([{$group:{_id: "  $gender  " ,objects:{$push: "  $$ROOT  " }}}])

$match

过滤数据,输出符合条件文档
 #  查询年龄大于20的学生 
db.stu.aggregate([{$match:{age:{$gt:20 }}}])

  #  查询年龄大于20的男、女生人数 
db.stu.aggregate([{$match:{age:{$gt:20}}},{$group:{_id: "  $gender  " ,counter:{$sum:1}}}])

$project

修改输出文档的结构
 #  查找学生姓名、年龄 
db.stu.aggregate([{$project:{ "  _id  " :0, "  name  " :1, "  age  " :1 }}])

  #  查询男生、女生人数,但仅输出人数 
db.stu.aggregate([{$group:{_id: ‘  $gender  ‘ ,counter:{$sum:1}}},{$project:{_id:0,counter:1}}])

$sort

将输入文档排序后输出
 #  查询学生信息,按年龄升序 
db.stu.aggregate([{$sort:{age:1 }}])

  #  查询男生、女生人数,按人数降序 
db.stu.aggregate([{$group:{_id: ‘  $gender  ‘ ,counter:{$sum:1}},{$sort:{counter:-1}}])

$limit

限制聚合管道返回的文档数
 #  查询2条学生信息 
db.stu.aggregate([{$limit:2}])

$skip

跳过指定数量的文档,并返回余下的文档,$skip和$limi合用时,注意先写skip,再写limit
 #  查询从第3条开始的学生信息 
db.stu.aggregate([{$skip:2 }])

  #  统计男生、女生人数,按人数升序,取第二条数据 
db.stu.aggregate([{$group:{_id: "  $gender  " ,counter:{$sum:1}}},{$sort:{ "  counter  " :1}},{$skip:1},{$limit:1}])

$unwind

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

六、索引

提升查询速度

创建大量数据

 for (var i=0;i<1000000;i++){db.stu.insert({name: ‘  test  ‘ +i,num:i})}

性能分析工具:explain("executionStats")

查询语句.explain( "  executionStats  " )

‘millis‘后面显示的是查询时间,单位ms

建立索引

db.集合.ensureIndex({属性:1或-1})  #  1表示升序,-1表示降序,建立后的索引名称为"属性_1"或者"属性_-1" 

例如:db.stu.ensureIndex({name:1}),建立后的索引名称为"name_1"

建立唯一索引

db.集合.ensureIndex({属性:1},{ "  unique  " :true})

建立联合索引

db.集合名.ensureIndex({属性1:1,属性2:1...})

查看索引

db.集合名.getIndexes()

删除索引

db.集合名.dropIndex( "  索引名称  "  )  

七、数据库安全

为了更安全的访问mongodb,需要访问者提供用户名和密码,于是需要在mongodb中创建用户。mongodb数据库采用了角色-用户-数据库的安全管理方式。

常用系统角色如下:

root:只在admin数据库中可用,超级账号,超级权限 Read:允许用户读取指定数据库 readWrite:允许用户读写指定数据库

创建超级管理用户:

use admin  #  首先切换到admin数据库 
 
db.createUser({
    user:  ‘  用户名  ‘  ,
    pwd:  ‘  密码  ‘  ,
    roles:[{role:  ‘  root  ‘ ,db: ‘  admin  ‘  }]
}) 

启用安全验证

修改配置文件( /etc/mongodb.conf)
 #  noauth = true 
auth = true  #  开启安全验证 
重启服务
sudo service mongodb restart
终端连接
 #   sudo mongo -u ‘用户名‘ -p ‘密码‘ --authenticationDatabase ‘数据库名‘  
sudo mongo -u  ‘  admin  ‘  -p  ‘  密码  ‘  --authenticationDatabase  ‘  admin  ‘ 

普通用户管理

首先使用超级管理员登陆,然后再进行用户管理操作 创建普通用户
 db.createUser({
    user:  ‘  用户名  ‘  ,
    pwd:  ‘  密码  ‘  ,
    roles:[{role:  ‘  readWrite  ‘ ,db: ‘  数据库名  ‘ }...]  #  数组里可以有多个角色文档,比如用户在不同的数据库里都有读写权限 
})

查看当前数据库的用户

show users
修改用户:可以修改pwd、roles属性
db.updateUser( ‘  用户名  ‘ ,{pwd: ‘  新密码  ‘ ,roles:[{ ‘  新角色  ‘ }...]})
删除用户
use admin   #  切换到admin数据库 
db.system.users.remove(条件)
终端连接
 sudo mongo -u  ‘  用户名  ‘  -p  ‘  密码  ‘  --authenticationDatabase  ‘  数据库名  ‘  

八、复制

复制提供了数据的冗余备份,并在多个服务器上存储数据的副本,允许从硬件故障和服务中断中恢复数据,能够实现无宕机维护(自动故障转移与自动恢复)。

复制至少需要2个节点,其中1个为主节点,其它均为从节点。任何节点均可以成为主节点。

主节点负责所有写入操作,从节点定期轮询主节点获取这些操作并执行这些操作,从而保证从节点的数据与主节点一致。

设置复制节点

创建数据库文件存放目录(自定义)
mkdir ~/Desktop/ t1
mkdir  ~/Desktop/t2
使用如下格式启动mongod,如果在同一台主机上,注意port不能相同,replSet的名称必须是一致的(名称可以自定义)
sudo mongod --bind_ip 192.168.196.128 --port 27017 --dbpath ~/Desktop/t1 -- replSet rs0
sudo mongod  --bind_ip 192.168.196.128 --port 27018 --dbpath ~/Desktop/t2 --replSet rs0
连接主服务器(自定义一个)
sudo mongo --host 192.168.196.128 --port 27017
初始化
rs.initiate()

哪个服务器执行初始化,哪个服务器就作为主节点,rs是mongo服务器中专门用于复本集操作的内置对象

查看当前状态
rs.status()
添加副本集
rs.add( "  192.168.127.128:8899  " )
连接从服务器
sudo mongo --host 192.168.196.128 --port 27018
从服务器设置
rs.slaveOk()

主服务器插入数据,从服务器就可以读取数据了

删除从节点
rs.remove( ‘  192.168.196.128:27018  ‘ )  #  需要在主服务器操作 

关闭主服务器后再重新启动,会发现原来的从服务器变为了主服务器,新启动的服务器(原来的主服务器)变为了从服务器,但是注意重新设置rs.slaveOk()

九、备份与恢复

备份

语法
sudo mongodump -h 服务器地址 -d 需要备份的数据库 -o 备份数据存放目录
mkdir ~/Desktop/test1_bak  #  创建存放备份数据的目录 
sudo mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1_bak

恢复

语法
sudo mongorestore -h 服务器地址 -d 恢复后数据库名 --dir 备份数据所在位置
sudo mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1_bak/test1

十、python交互

安装pymongo包

sudo pip3 install pymongo

引入包

 import  pymongo

建立连接并创建客户端

有安全认证:client=MongoClient( "  mongodb://用户名:密码@host:27017/数据库名称  "  )
无安全认证:client =MongoClient( "  mongodb://localhost: 27017  " )

获得数据库(以test数据库为例)

db =  client.数据库名
例如:db  = client.test

获得集合stu

stu = db.stu

数据操作

查询 find_one 查找单个文档
stu1 = stu.find_one({条件})  #  返回一条文档,字典类型 
find 查找多个文档
cursor = stu.find({条件})  #  返回迭代器对象cursor  
#  方式1:用for循环迭代取值 
 for  s  in   cursor:
  print (s)  #  字典类型 

 #  方式2:用next取值 
s1 =  next(cursor)
s2  =  next(cursor)
... 
插入 insert_one 插入一条文档
stu.insert_one(文档)
insert_many 插入多条文档
stu.insert_many([文档1,文档2...])
更新 update 更新匹配到的第一条整条文档
stu.update({条件},文档)  #  注意条件中的数字一定要写成字符串类型 
update_one 与$set一起使用,指定属性修改匹配到的第一条文档
stu.update_one({条件},{$set:{文档}})
update_many 与$set一起使用,指定属性修改多条文档
stu.update_many({条件},{$set:{文档}})
删除 delete_one 删除单条文档
stu.delete_one({条件})
delete_many 删除多条文档
stu.delete_many({条件})

 






MongoDB数据库的使用

标签:字典   引入   mongod   pretty   cat   投影   size   cti   去重   

查看更多关于MongoDB数据库的使用的详细内容...

  阅读:34次