mongodb学习笔记

数据库 mongodb (芒果数据库)
数据存储阶段
文件管理阶段(.txt .doc .xls)
优点:数据可以长期保存,可以储存大量的数据,使用简单
缺点:数据一次性差,数据查找修改不方便

几个概念
数据:能够输入到计算机中并被识别处理的信息集合
数据结构:研究一个数据集合中数据之间关系的
数据库:按照数据结构,储存管理数据的仓库。数据库是在数据库管理系统管理和控制下,在一定介质上的数据集合
数据库管理系统:管理数据库的软件,用于建立和维护数据库

mysql和mongodb概念对比
MySQL                 mongo                 含义
database              database              数据库
table                 collection            表/集合
column                field                 字段/域
row                   document              记录/文档
index                 index                 索引

创建一个叫stu的数据库
use stu

* use实际功能是表示选择使用哪个数据库,当这个数据库不存在时即表示创建该数据库
* 使用use后数据库并不会马上被创建,而是需要插入数据后数据库才会创建

查看数据库
show  dbs 查看有那些数据库

数据库名称规则
1.原则上时任意满足以下几条的utf-8字符
2.不能是空字符,不能含有空格‘ ’点‘.’ '/' '\' '\0'
3.习惯上使用英文小写
4.长度不超过64字节
5.不能使用admin local config 这样的名字

admin:存储用户
local:存储本地数据
config: 存储分片配置信息

db: mongo系统全局变量 代表你当前正在使用的数据库
db 默认test 如果插入数据即创建test数据库

数据库的备份与恢复
备份 mongodump -h dbhost(主机地址) -d dbname(数据库名) -o dbdir(文件地址)
会自动生成一个数据库名的文件下

恢复 mongorestore -h <dbhost>(主机地址):<port>(端口) -d dbname(数据库名称) <path>(备份文件夹地址)

数据库的监测命令
mongostat
insert query update delete :每秒增删查改的次数
getmore command 每秒运行命令次数
dirty used flushes 每秒操作磁盘次数
vsize res 使用虚拟内存和物理内存

mongotop
监测每个数据库的读写时长

ns           total         read          write
数据集合      总时长         读时长        写时长

删除数据库
db.dropDatabase()  删除的是所在的库即输入db后返回的库

集合的创建(类似于表)
db.createCollection(collection_name) 创建一个集合
show tables/collections 展示有哪些集合

集合的命名规则:
1.不能为空字符串,不能有‘\0’
2.不能以system.开头 这是系统集合的保留前缀
3.不能和保留字重复

创建集合2
当向一个集合中插入文档时,如果该集合不存在则自动创建
db.collectionName.insert()

删除集合
db.collectinName.drop()

集合重命名
db.collectionName.renameCollection('new_name')
e.g. db.class2.renameCollection('class0') 将class1重命名为class0

文档
mongodb 中文档的组织形式
键值对组成文档---》 类似Pytnon中的字典,但不是字典
bson ----》 json ----》 JavaScript
mongodb中文档的数据组织形式为bson格式,类似Python的字典,也是由键值对组成
文档中键的命名规则:
1.utf-8格式字符串
2.不能有\0 习惯上不用.和$
3.以_开头的多为保留键,自定义时一般不以_开头

注意:在bson中文档键值对是有序的,mongodb中严格区分大小写

值: mongodb的支持数据类型
类型          值
整型          整数
布尔类型       true false
浮点型         小数
Arrays        数组类型[1,2,3]
Timestamp     时间戳
Date          时间日期
Object        内部文档
Null          空值
Symbol        特殊字符
String        字符串
Binary data   二进制字串
code          代码
regex         正则表达式
ObiectId      ObjectID字串  用来提供一个主键(类似于sys_guid())

ObjectID:  系统自动为每个文档生成的不重复的主键,为24位的16进制数
8 文档创建时间   6机器ID  4进程ID   6计数器

集合中文档特点:
1. 集合中的文档域不一定相同
2. 集合中的文档结构不一定相同

集合设计原则:
1. 集合中的文档尽可能描述的数据类似
2. 同一类文档放在相同的集合,不同的文档分集合存放
3.层次的包裹不宜太多

插入文档
db.collectionName.insert()
查看插入结果 db.class0.find()
插入多条文档
db.collectionName.inser([{'name':'ahua','age':28},{},{}])  每个{}代表一条
可以认为插入_id来自己设定_id的值不会再自动生成,并且该值不允许重复

save  插入数据
db.collectionName.save()
在不加_id时使用同insert
如果使用save插入的时候加了_id,则如果_id值不存在则正常插入,如果该值存在,则修改原来内容。为完全修改,原来没有的字段添加,
多余的字段删除
save无法一次插入多个文档


查找操作
db.collectiomName.find() --> select * from tablename
find(query,field)
功能: 查找所有符合条件的文档
参数: query:筛选条件  相当于where语句
      field:展示的域  相当于select的展示部分 *
返回: 返回所有查找到的内容
field参数: 选择要展示的域  传一组键值对
键表示域名
值表示是否显示改域 0 表示不显示  1 表示显示
如果某个域给定0 则表示不显示该域,其他的域均显示
如果某个域给定1 则表示显示该域,其他的域均不显示
_id永远默认为显示,除非设置为0,而且_id设置为0并不影响其他的域
除_id外其他的域必须拥有相同的设置,全为0或者全为1
如果不屑该参数则表示显示所有域内容

query:以键值对的形式给出查找条件
查找年龄17 e.g.  db.class0.find({age:17},{_id:0})
如果不写第一个参数则表示查找所有内容

findOne()
功能参数和find()完全相同,只是只返回只返回第一条查找到的文档

比较操作符
$eq 等于
e.g. db.class0.find({age:{$eq:17}},{_id:0})
筛选年龄等于17的
db.class0.find({age:17},{_id:0})

$lt 小于 <
e.g.  db.class0.find({age:{$lt:17}},{_id:0})
mongo中字符也可以比较大小

$lte 小于等于
e.g.  db.class0.find({age:{$lte:17}},{_id:0})

$gt 大于
e.g. db.class0.find({age:{$gt:17}},{_id:0})

$gte 大于等于
e.g. db.class0.find({age:{$gte:17}},{_id:0})

$ne 不等于
e.g. db.class0.find({age:{$ne:17}},{_id:0})
如果一个文档没有这个age域则显示为不等于

$in 包含
e.g. db.class0.find({age:{$in:[16,17,18]}},{_id:0}) 年龄在17,18,16当中的数据

$nin 不包含  相当于not in
e.g. db.class0.find({age:{$nin:[16,17,18]}},{_id:0}) 年龄不在17,18,16当中的数据


逻辑操作符
$and 逻辑与
年龄小于19 并且 性别为男
e.g. db.class0.find({age:{$lt:19},sex:'m'},{_id:0})
年龄小于19 并且 大于15
e.g. db.class0.find({age:{$lt:19,$gt:15}},{_id:0})
用and来表示
e.g. db.class0.find({$and:[{age:17},{name:'lei'}]})

$or 逻辑或
e.g. db.class0.find({$or:[{age:{$lt:21}},{name:'swk'}]},{_id:0})
年龄小于18 或 年龄大于25
e.g. db.class0.find({$or:[{age:{$lt:18}},{age:{%gt:32}}]},{_id:0})

$not 逻辑非
e.g. db.class0.find({age:{$ne:17}},{_id:0}) ---> db.class0.find({age:{$not:{$eq:17}}},{_id:0})

$nor 既不也不(表示集合中的条件都不具备)
e.g. db.class0.find({$nor:[{age:{$gt:18}},{sex:'m'}]},{_id:0})

条件混合 (年龄小于20 或者 姓名为Lily) 并且性别为女的人
e.g. db.class0.find({$and:[{%or:[{age:{$lt:20}},{name:'Lily'}]},{sex:'w'}]},{_id:0})

年龄小于或等于17 或者 (姓名大于Tom 并且 年龄大于100)
e.g. db.class0.find({$or:[{age:{$lte:17}},{$and:[{name:{$gt:'Tom'},{age:{$gt:100}}}]}]})

数据查找:
查看数组中包含某一项的
db.class1.find({hobby:'吃'},{_id:0})

$all
查找一个数组中同时包含多项的文档
db.class.find({hobby:{$all:['拍电影','做代言']}},{_id:0})
查找hobby数组中既有拍电影,又有做代言的文档

$size
查找数组元素个数为指定个数的文档
db.class1.find({hobby:{$size:3}},{_id:0})
查看数组中hobby包含三项的

数组切片显示
$slice
对数字进行切片显示
db.class1.find({hobby:{$size:3}},{_id:0,hobby:{$slice:2}})
只显示hobby数组中的前两项
db.class1.find({hobby:{$size:3}},{_id:0,hobby:{$slice:[1,2]}})
跳过第一项,显示后面两项

其他查找方法
$exists
判断一个域是否存在
db.class0.find({sex:{$exists:true}},{_id:0}) #查找存在sex域的文档
db.class0.find({sex:{$exists:flase}},{_id:0}) #查找不存在sex域的文档

$mod
做除数余数查找
db.class0.find({age:{$mod:[2,1]}},{_id:0}) 查找年龄是但是的文档

$type
查找指定数据类型的文档
db.class0.find({name:{$type:1}},{_id:0}) type对应数字参照
查找name中数据类型为1的文档

进一步的信息筛选

distinct()
功能:查看一个集合中某个域值的覆盖范围
db.class0.distinct('age') 查看age这个域都有哪些值  就是去重

pretty
功能:将查询结果格式化显示
db.class0.find().pretty()

limit(n)
显示前n条
db.class0.find({},{_id:0}).limit(3) #显示查询结果的前三条

skip(n)
功能:显示时跳过前n条

count()
功能:对查询结果计数统计
db.class0.find({sex:'m'},{_id:0}).count() #统计性别为男的数量


sort()
功能:对查找结果排序 1 表示按照升序排序 -1 表示按照降序排序
db.class0.find({age:{$exists:true}},{_id:0}).sort({age:-1}) 将存在age的数据降序排列

复合排序 sort({age:1,name:-1})


删除文档
db.collectionNsme.remove(query,justOne)
功能:删除指定的文档
参数: query: 筛选要删除的文档,类似where语句 用法同查找操作
      justOne:布尔值 默认false表示删除所有筛选数据
               如果赋值为true 则表示只删除第一条复合文档
db.class0.remove({$or:[{age:{$exists:flase}},{age:{$gt:100}}]}) #删除没有age域和年龄大于100的文档

删除集合中所有文档
db.collectionName.remove({})

修改数据
db.collectionName.update(query,update,upsert,multi)
功能: 修改一个文档
参数: query:筛选要修改的文档 相当于where子句 用法同查找
      update: 将数据更新为什么内容 相当于set 需要使用修改器操作符
      upsert: 布尔值 默认为false 表示如果query的文档不存在则无法修改
               如果设置为true 表示如果query的文档不存在 则根据query和update参数插入新的文档
      multi:  bool值 默认为flase 如果有多条符合筛选条件的文档则只修改第一条
               如果设置为true 则修改所有符合条件的文档

db.class0.update({name:'阿红'},{$set:{age:24}}) #将名字为阿红的age修改为24
db.class0.update({sex:'w'},{$set:{age:20}},false,true) 可以同时修改多条匹配到的文档

修改器操作符
$set 修改一个域的值
     增加一个域
db.class0.update({name:'阿红'},{$set:{sex:'w'}}) 为阿红加一个sex域

$unset
删除一个域
db.class0.update({name:'八戒'},{$unset:{sex:0,age:0}}) 将sex和age(后面数字习惯写1,0都表示删除)

$rename
修改一个域的名称
db.class0.update({},{$rename:{sex:'gender'}},false,true) 将所有的sex域修改为gender

$setOnInsert
如果update操作插入新的文档,则补充插入内容

如果插入数据则同时插入sex和tel域内容;   #当集合中不存在name为阿华的文档时将阿华插入进去,并自动补足sex和tel两项
db.class0.update({name:'阿华'},{$set:{age:21},$setOnInsert:{sex:'m',tel:'123456'}})

$inc
加减修改器 db.class0.update({age:{$lt:18}},{$inc:{age:1}},false,true) #将所有小于18岁的人加1岁

$mul
乘法修改器 db.class0.update({age:{$lt:18}},{$mul:{age:1}},false,true) 可乘以正数 负数 小数都可以

$min
设定最小值:如果筛选的文档指定的域值小于min值则不修改,如果大于min值则改为min值
db.class0.update({},{$min:{age:19}},false,true) 将大于19岁的修改为19

$max
设定最大值:瑞国筛选的文档指定值大于max值则不变,如果小于max值则修改为max值
db.class0.update({},{$max:{age:20}},false,true) 将小于20的修改为20

数组修改器
$push 向数组中添加一项
db.class1.update({name:'abby'},{$push:{socre:30}})  #将abby的分数数组中加30
{$push:{数组的名称:添加的值}}

$pushAll 向数组中添加多项
db.class1.update({name:'abby'},{$pushAll:{socre:[10,20]}}) 将多项添加到数组里面

$each 逐个操作
db.class1.update({name:'abby'},{$push:{socre:{$each:[10,5]}}}) #利用each依次添加10和20

$position
选择数据位置进行操作  必须跟each一起使用
db.class1.update({name:'lucy'},{$push:{score:{$each:[10,10],position:1}}}) 在数组score中的1位置依次插入10

$sort
对数据进行排序,并且必须跟$each一起使用
db.class0.update({name:'lili'},{$push:{$each:[],$sort:1}}) 将sorce数组重新排序
db.class0.update({name:'lili'},{$push:{$each:[10,10],$sort:1}})  先依次插入10,10再进行排序

$pull 从数组中删除一个元素
db.class1.update({name:'lily'},{$pull:{score:5}}) 将score中的5删除掉

$putAll 从数组中删除多个元素
db.class1.update({name:'lili'},{$putAll:{score:[10,20]}})

$pop 弹出数组中的一项
db.class1.update({name:'lily'},{$pop:{score:1}})  {$pop:{数组:1 弹出第0项/-1 弹出最后一项}}

$addToSet #向数组中插入一个元素,但是该元素不能和其他元素重复
db.class1.update({name:'lily'},{$addToSet:{score:66}}) 如果已经存在66则无法插入,如果不存在则插入66

数据类型补充

时间类型
mongo中储存时间的格式: ISODate
db.class1.insert({title:'python',date:new Date()})

方法1 自动生成当前时间 new Date()
db.class1.insert({title:'python',date:new Date()})

方法2 生成当前时间
db.class2.insert({title:'python',date: ISODate("2018-05-24T03:49:08.095Z")})

方法3 将生成时间变为字符串存储
db.class2.insert({title:'python',date:Date()})

指定时间的转换
ISODate()
功能: 生成mongo时间类型
参数: 如果不加参数则生成当前时间
      参数格式  "2018-11-11 11:11:11"
               "20180101 11:11:11"
               "20181102"

db.class2.insert({title:'python',date:ISODate("20180101 11:11:11")})

时间差获取 1900-01-01到现在的秒数
db.class2.insert({title:'python',date:ISODate().valueOf()})


null

1. 如果某个域存在却没有值可以设置为null
db.class10insert({title:'gnfg',price:null})

2. 如果某个域不存在可以用null来进行匹配
db.class2.find({date:null}) 用来匹配不存在date域的数据

Object类型 (值是一个文档)
db.class2.insert({title:'gngfnf',author:'cgsdb',publication:{price:46,publication_date:'2017-01-01',publisher:'人民教育'}})
域中的值为字典
查询 db.class2.find({'publication.publisher':'人民教育'},{_id:0}) {'外层结构.内层结构':'查询数据'}
当使用外层文档引用内部文档的时候可以用.的方法引用在使用时需要加上引号

db.class2.update({titile:'gngn'},{$set:{'publication.price':58.8}})
db.class1.update({name:'lily'},{$set:{'score.0':60}}) 将score数组中的第一个值修改为60
db.class1.find({'score.0':{$gt:90}}) 查询score数组中第一个值大于90的文档

文档查找结果的有序性
db.class1.find({},{_id:0})[0]  通过[]加下标的方法查找第几条,从0开始 0为第一条


索引
指的是建立指定键值及所在文档中存储位置的对照清单。使用索引以方便我们进行快速查找,减少遍历次数,提高查找效率。

mongo中如何创建索引

ensureIndex
功能: 创建索引
参数: 索引类别,索引选项

db.class0.ensureIndex({'name':1}) 1表示为该域创建正向索引, -1 表示逆向索引 看查找后来数据还是早期数据
_id 域会自动创建索引

查看一个集合的索引
db.class0.getIndexes() v:索引版本  key:对应列:正向或逆向  name:索引名称  ns:对应集合

删除索引
dropIndex() 删除某一个索引()里面为索引名 db.class0.dropIndex('name_1')
也可以用创建索引时候的键值对来进行删除 db.class0.dropIndex({name:1})
参数: 删除索引的名称

dropIndexes() 功能: 删除所有索引

索引类型
复合索引 db.class0.ensureIndex({name:1,age:1}) 用name和age来创建复合索引(根据多个域创建一个索引)

数组索引
如果对某个数据域创建索引,那么表示对数组中的每个值均创建了索引,通过数组中单个值查询,也是索引查询

子文档索引
如果对一个域创建索引,值是一个文档则也会创建索引
如果对子文档进行索引创建,则通过子文档查找为索引查找

覆盖索引
查找时值获取索引项的内容,而不去获取原数据中的其他内容,这样就不去连接原来的数据直接返回i即可

name为索引,显示也只要name域
db.class0.find({name:'lily'},{_id:0,name:1})

唯一索引
创建索引时希望索引域的值均不相同,也可以据此限制一个域的值
db.class0.ensureIndex({age:1},{'unique':true}) 为age域添加唯一索引
当对某个域创建了唯一索引后,即不允许再插入相同的值的文档

稀疏索引(间隙索引)
只针对有指定域的文档创建索引表,没有该域的文档,不会插入到索引表中
db.class2.ensureIndex({'date':1},{sparse:true})

索引约束:
1.影响数据的插入,删除,修改操作。当数据发生改变时,索引表必须同步更新
2.索引也是需要占用一定的空间资源

综上:当数据库大量的操作时插入,修改,删除操作,而非查询操作时,不适合创建索引。数据量比较小时,考虑到空间成本也不适合创建索引。
即使适合创建索引的情况,也不是索引越多越好。

聚合
多数据文档进行整理统计
db.collectionName.aggregate()
功能:聚合函数,配合聚合条件进行数据整理统计
参数:聚合条件

聚合操作符
$group 分组 和分组操作符配合使用确定按什么分组

分组操作符
$sum 求和  db.class0.aggregate({$group:{_id:'$gender',num{$sum:1}}})
格式{$group:{_id:'$进行分组的字段',统计数量的列名:{$sum:1(没有一个就计数为1)}}} 分组字段必须用引号引起并加$前缀

db.class0.aggregate({$group:{_id:'$gender',num{$sum:'age'}}})
将统计出来的年龄求和,按性别来统计总年龄

$age 求平均数
db.class0.aggregate({$group:{'$gender',num:{$avg:'%age'}}}) 按性别分组求平均年龄

$min 求最小值
db.class0.aggregate({$group:{'$gender',num:{$min:'%age'}}}) 按性别分组求最小值

$max 求最大值
db.class0.aggregate({$group:{'$gender',num:{$max:'%age'}}}) 按性别分组求最大值

$first 返回每组第一个文档指定域值
db.class0.aggregate({$group:{'$gender',name:{$first:'%name'}}})

$last 返回每组最后一个文档指定域值
db.class0.aggregate({$group:{'$gender',name:{$last:'%name'}}})

$project 用于修饰文档的显示结构
db.class0.aggregate{{$project:{_id:0,name:1,age:1}}}
db.class0.aggregate{{$project:{_id:0,Name:'$name',Age:'$age'}}} 将name和age两域用Name和Age显示

$match 过滤数据
操作符的值同find中的query
db.class0.aggregate({$match:{gender:'m'}})  过滤性别为男的

$skip 跳过前几条文档
db.class0.aggregate({$skip:5})

$limit 显示几条文档
db.class0.aggregate({$limit:5})

$sort 排序
db.class0.aggregate({$sort:{name:1}})

聚合管道
将前一个聚合操作的解惑给下一个聚合操作继续执行
db.collectinName.aggregate([聚合1,聚合2,....])

固定集合
mongo中可以创建大小固定的集合,称之为固定集合,固定集合的性能出色,适用于很多场景
比如;日志处理, 临时缓存

特点:插入速度快
     顺序需查询速度快
     能够淘汰早期数据
     可以控制集合空间

创建:db.createCollection(collectionNaame,{capped:true,size:1000,max:1000})
size:设置固定集合的大小 kb
max:最多能容纳多少文档

创建一个最多包含三条文档的集合
db.createCollection('log',{capped:true,size:10,max:3})

文件存储
数据库存储文件的方式
1.在数据库中以字符串的方式存储文件在本地的路径

有点:节省数据库空间
缺点:当数据库或者文件位置发生变化即需要相应修改数据库内容

2.将文件以二进制数据的方式存放在数据库里面

优点:文件存入数据库,数据库在,文件即不会丢失
缺点:当文件较大时,数据库空间占用大,提取困难

mongo中 使用GridFS方法 大文件存储
GridFS:时mongodb中大文件存储的一种方案,mongo中认你为大于16M的文件为大文件

方案解释:
在mongodb数据库中 创建两个集合 共同完成对文件的存储
fs.files:存储文件的下能管信息,比如:文件名 文件类型
fs.chunks:实际存储文件内容,以二进制方式分块存储。将大文件分为多个小块,每块占一个空间

mongofiles --d dbname put file
               数据库      要存储的文件
如果数据库并不存在则自动创建

游标
1.防止网络拥塞,造成数据传输慢
2.提高用户解析体验,可以后端解析

var cursor = db.class0.find() 创建游标
cursor.hasNext() 查看是否有下一个数据
cursor.next() 获取下一个数据

Python --->> mongodb编程接口 pymongo

操作步骤
1.创建mongo数据库的连接对象
conn=MongoClient('localhost',端口)
2.生成数据库对象
db = conn.stu 选择要使用的数据库
3.生成集合对象
my_set = db.class0 选择要使用的表
4.增删改查索引聚合操作
插入数据
my_set.insert({'name':'zhangtielin'})
my_set.insert_many([{'name':'hvnvh'},{'name':'nf'}]) 必须传入一个列表
my_set.insert_one({'name':'bgf'})
my_set.save({'name':'fngf'})
conn.close()

删除数据
my_set.remove(self,spec_or_id=None, multi=True)
spec_or_id:要删除的文档
multi:是否删除所有 True 删除所有
my_set.remove({'name':'vngfn'})
my_set.remove({'name':'dfgdfg'},multi = False) 只删除一条name为目标的文档

数据查找
find()
功能:查找数据库内容
参数:同 mongo shell find()
cursor = my_set.find({},{'_id':0})

for i in cursor:
    print(i['name'],'----','i['king']')

cls = db.class0


sort()
mongoshell ---》 sort({'name':1})
pymongo ---> sort([('name',1)]) *进行排序时游标要确保没有被访问过

find_one 返回值时一个字典
dic = {'$or':[{'name':{'$gt':'Tom'}},{'gender':'w'}]}
data = cls.find_one(dic)
print(data)  find_one 等同于find

修改操作
update():参数跟mongoshell中update相同
my_set.update ({'name':'zgl'},{'$set':{'name':'gl'}})
my_set.update({'name':'bb'},{'$set':{'king':'wzt'}},upsert = True)  没有匹配到则插入
my_set.update({'king':'kx'},{'$set':{'king_name':'xy'}},multi = True) 修改多条文档
update_many():匹配多个文档时全部修改
my_set.update_many({'king':'vb'},{'$set':{'king_name':'vnv'}}) 不需要加multi参数
update_one():只修改匹配到的第一条文档

编程中mongo的数据类型null 可以用python中的None替代

my_set.find_one_and_delete({'name':'bb'}) 查找并删除,查找结果会返回

索引和聚合操作演示
创建索引  index = my_set.ensure_index('name') 在name列上添加索引
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值