数据库 MongoDB (芒果数据库)
数据存储阶段
文件管理阶段 (.txt .doc .xls)
优点 : 数据可以长期保存
可以存储大量的数据
使用简单
缺点 : 数据一致性差
数据查找修改不方便
数据冗余度可能比较大
数据库管理阶段
优点 : 数据组织结构化降低了冗余度
提高了增删改查的效率
容易扩展
方便程序调用,做自动化处理
缺点 :需要使用sql 或者 其他特定的语句,相对比较复杂
几个概念
数据 : 能够输入到计算机中并被识别处理的信息集合
数据结构 :研究一个数据集合中数据之间关系的
数据库 : 按照数据结构,存储管理数据的仓库。数据库是在数据库 管理系统管理和控制下,在一定介质上的数据集合。
数据库管理系统 :管理数据库的软件,用于建立和维护数据库
数据库系统 : 由数据库和数据库管理系统,开发工具等组成的集合
关系型数据库
采用关系模型来组织数据结构的数据库 (二维表)
Oracle DB2 SQLServer MySql SqLite(Python标准库支持)
优点 :容易理解,类似我们常见的表格
使用方便,都是使用sql语句,SQL语句非常成熟
数据一致性高,冗余度低,完整性好
技术成熟,可以使用外部链接等比较复杂的操作
缺点 :不能很好的满足高并发需求,每次都需要进行sql语句的解析
针对含量数据的瞬间爆发读写性能不足,关系型数据库内部每步操作都需要加锁保证操作的原子性
数据扩展普遍比非关系型困难
数据一致性高,有时会浪费大量空间
非关系型数据库 (NoSql --> Not only Sql)
优点 : 高并发,大数据读写能力强
支持分布式,容易扩展
弱化了数据结构,降低了数据的一致性
缺点 : 通用性差,没有像sql那样一致的操作
操作灵活,容易混乱
没有join,有的数据库事务支持等操作
Nosql的使用情况:
1. 数据一致性要求低
2. 数据库并发处理要求高
3. 数据库设计时对大小的估算不确定,需要分布拓展
4. 给定的数据比较容易建立起Nosql的模型
Nosql分类:
1. 键值型数据库
Redis oracle BDB Tokyo
2. 列存储数据库
HBase
3. 文档型数据库
MongoDB CouchDB
4. 图形数据库
MongoDB(非关系型 --》文档型数据库)
1. 由c++编写的数据库管理系统
2. 支持非常丰富的增删改查数据操作
3. 支持非常丰富的数据类型
4. 使用方便,便于部署,支持分布,容易拓展
5. 支持众多的编程语言接口 (python ruby c++ c# PHP)
MongoDB 安装
自动安装
sudo apt-get install mongodb
默认安装位置 /var/lib/mongodb
配置文件 /etc/mongodb.conf
命令集 /usr/bin /usr/local/bin
手动安装
1.下载MongoDB (开源)
www.mongodb.com ---》 Download ---》 community server
选择合适版本下载
2. 选择安装目录解压 (/usr/local /opt)
tar解压后得到mongo文件夹
3. 将文件夹下的命令集目录 (bin目录)添加到环境变量
PATH=$PATH:/opt/mongo....../bin
export PATH
将以上两句写在 /etc/rc.local
4.重启系统
mongodb 命令
设置数据库存储位置
mongod --dbpath 目录
设置端口号
mongod --port 8888
*如果不设置则使用默认端口号 27017
mongo
进入mongo shell界面 mongodb的交互界面用来操作数据库
退出 mongo shell : quit()
组成结构: 键值对 ---》 文档 ----》集合 ----》 数据库
----------------------------
ID | name | age
----------------------------
1 | Lily | 17
----------------------------
2 | Lucy | 18
----------------------------
{
"_id":ObjectId("abcd1234afhkasyr"),
"name":"Lily",
"age":17
},
{
"_id":ObjectId("abcd1234afasfsyr"),
"name":"Lucy",
"age":18
}
mysql 和 mongodb 概念对比
mysql mongo 含义
database database 数据库
table collection 表/集合
column field 字段/域
row document 记录/文档
index index 索引
创建数据库
use databasename
e.g.
创建一个叫 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
e.g. mongodump -h 127.0.0.1 -d stu -o student
将本机下 stu 数据库备份到 当前目录的student文件夹中
会在student文件夹中自动生成一个stu文件夹则为备份文件
恢复 mongorestore -h <dbhost>:<port> -d dbname <path>
e.g. mongorestore -h 127.0.0.1:27017 -d test student/stu
将student文件夹下的备份文件stu恢复到本机的test数据库
数据库的监测命令
mongostat
insert query update delete :每秒增查改删的次数
getmore command 每秒运行命令次数
dirty used flushes 每秒操作磁盘的次数
vsize res 使用虚拟内存和物理内存
mongotop
监测每个数据库的读写时长
ns total read write
数据集合 总时长 读时长 写时长
删除数据库
db.dropDatabase()
删除db所代表的数据库
集合的创建
db.createCollection(collection_name)
e.g. db.createCollection("class2")
在当前数据库下创建一个名字为class2的集合
查看数据库中集合
show tables
show collections
集合的命名规则:
1. 不能为空字符串,不能有'\0'
2. 不能以 system.开头 这是系统集合的保留前缀
3. 不能和保留字重复
创建集合2
当向一个集合中插入文档时,如果该集合不存在则自动创建
db.collectionName.insert()
e.g. db.class0.insert({a:1})
如果class0不存在则会创建class0集合并插入该数据
删除集合
db.collectionName.drop()
e.g. db.class0.drop()
删除class0集合
集合重命名
db.collectionName.renameCollection('new_name')
e.g. db.class2.renameCollection('class0')
将class2重命名为class0
文档
mongodb 中文档的组织形式
键值对组成文档 -----》 类似Python中的字典
bson -----》 json -----》 JavaScript
mongodb 中文档的数据组织形式为bson格式,类似Python的字典,也是由键值对构成
文档中键的命名规则 :
1. utf-8格式字符串
2. 不用有\0 习惯上不用 . 和 $
3. 以_开头的多位保留键,自定义时一般不以_开头
注意 : 文档键值对是有序的
mongodb中严格区分大小写
值 : mongodb的支持数据类型
支持的数据类型
类型 值
整型 整数
布尔类型 true false
浮点型 小数
Arrays 数组类型 [1,2,3]
Timestamp 时间戳
Date 时间日期
Object 内部文档
Null 空值
Symbol 特殊字符
String 字符串
Binary data 二进制字串
code 代码
regex 正则表达式
ObjectId ObjectId子串
ObjectId : 系统自动为每个文档生成的不重复的主键
键名称: _id
值 : ObjectId("5b03b823e64cb5d90e9c8f5c")
24位16进制数
8 文档创建时间 6机器ID 4进程ID 6计数器
文档中键 -----》 域/字段
文档 ---------》 记录
集合中文档特点:
1. 集合中的文档域不一定相同 ---》不保证数据一致性
2. 集合中的文档结构不一定相同
集合设计原则:
1.集合中的文档尽可能描述的数据类似
2.同一类文档放在相同的集合,不同的文档分集合存放
3.层次的包裹不宜太多
插入文档
db.collectionName.insert()
e.g.
db.class0.insert({name:'Lucy',age:16,sex:'w'})
* 当作为文档插入时键可以不加引号
查看插入结果 db.class0.find()
插入多条文档
db.collectionName.insert([{},{},{}])
e.g. db.class0.insert([{'name':'阿花',age:28},{name:'阿红',age:26},{name:'阿彪',age:23}])
* _id 为系统自动添加主键,如果自己写_id域则会使用自己写的值。但是该值仍不允许重复。
save 插入数据
db.collectionName.save()
e.g.
db.class0.save({_id:2,name:'八戒',age:17,sex:'m'})
* 在不加_id是使用同 insert
* 如果使用save插入的时候加了_id,则如果_id值不存在则正常插入,如果该值存在,则修改原来内容
* save无法一次插入多个文档
作业 : 练习mongodb的数据库,集合创建删除
mongodb 插入练习
关系型数据库和非关系数据库都有什么特点?
mongodb的优点在哪里?
************************************************************第二天
复习 :
数据库创建删除: use 数据库名称
db.dropDatabase()
集合的创建和删除 db.createCollection('name')
db.collectionName.insert()
db.collectionName.drop() 删除
db.collectionName.renameCollection() 重命名
数据库的备份和恢复
mongodump (备份) mongorestore(恢复)
数据库的监测
mongostat mongotop
数据库配置
mongod --dbpath path --port 8888
数据的插入 : insert() save()
=====================================
db.collectionName 集合对象
获取集合对象 : db.getCollection('collection_name')
e.g.
db.getCollection("class0").insert({name:'悟空',age:1700})
查找操作
select ... from tableName where .....
db.collectionName.find() ---> select * from tableName
find(query,field)
功能 : 查找所有符合条件的文档
参数 : query : 筛选条件 相当于where字句
field : 展示的域 相当于select的展示部分
返回 : 返回所有查找到的内容
field 参数 : 选择要展示的域 传一组键值对
键表示域名
值表示是否显示该域 0 表示不显示 1 表示显示
* 如果某个域给定0 则表示不显示该域,其他的域均显示
如果某个域给定1 则表示显示该域 ,其他的域都不显示
* _id 永远默认为显示,除非设置为0
* 除_id外其他域 必须拥有相同的设置,全为0或者全为1
* 如果不写该参数则表示显示所有域内容
e.g. db.class0.find({},{_id:0,name:1,age:1})
query : 以键值对的形式给出查找条件
查找年龄 17
e.g. db.class0.find({age:17},{_id:0})
* 如果不写第一个参数则表示查找所有内容
findOne()
功能参数和find() 完全相同,只是只返回第一条查找到的文档
e.g. db.class0.findOne({age:17},{_id:0})
query的更多用法
操作符: 使用$符号注明一个特殊字符串,表示一定的含义
e.g. $lt 表示 小于
比较操作符
$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})
$nin 不包含
e.g. db.class0.find({age:{$nin:[16,17,18]}},{_id:0})
逻辑操作符
$and 逻辑与
年龄小于19 并且 性别为男
db.class0.find({age:{$lt:19},sex:'m'},{_id:0})
年龄小于19 并且 大于15
db.class0.find({age:{$lt:19,$gt:15}},{_id:0})
e.g. db.class0.find({$and:[{age:17},{name:'Lei'}]})
$or 逻辑或
e.g.
db.class0.find({$or:[{age:{$lt:22}},{name:'悟空'}]},{_id:0})
db.class0.find({$or:[{age:{$lt:18}},{age:{$gt:30}}]},{_id:0})
$not 逻辑非
e.g. db.class0.find({age:{$not:{$eq:17}}},{_id:0})
$nor 既不也不 (表示列表集合中的条件都不具备)
db.class0.find({$nor:[{age:{$gt:18}},{sex:'m'}]},{_id:0})
条件混合
(年龄小于20 或者 姓名为阿红) 并且 性别为女的人
db.class0.find({$and:[{$or:[{age:{$lt:20}},{name:'阿红'}]},{sex:'w'}]},{_id:0})
年龄小于等于17 或者 (姓名大于Tom 并且 年龄大于100)
db.class0.find({$or:[{age:{$lte:17}},{name:{$gt:'Tom'},age:{$gt:100}}]},{_id:0})
数组查找 :
查看数组中包含某一项的
e.g. db.class1.find({hobby:'吃'},{_id:0})
$all
查找一个数组中同时包含多项的文档
e.g. db.class1.find({hobby:{$all:['拍电影','代言']}},{_id:0})
查找hobby数组中既有拍电影,又有代言的文档
$size
查找数组元素个数为指定个数的文档
e.g. db.class1.find({hobby:{$size:3}},{_id:0})
查找hobby数组中包含三项的文档
数组切片显示
$slice
对数组切片显示
e.g.
db.class1.find({hobby:{$size:3}},{_id:0,hobby:{$slice:2}})
显示数组的前两项
e.g.
db.class1.find({hobby:{$size:3}},{_id:0,hobby:{$slice:[1,2]}})
跳过第一项,显示后面两项
其他查找方法:
$exists
判断一个域是否存在
e.g. 查找存在sex域的文档
db.class0.find({sex:{$exists:true}},{_id:0})
e.g. 查找不存在sex域的文档
db.class0.find({sex:{$exists:false}},{_id:0})
$mod
做除数余数查找
e.g.
查找年龄 被2除余1的文档
db.class0.find({age:{$mod:[2,1]}},{_id:0})
$type
查找指定数据类型的文档
e.g. 查找hobby中包含数据类型为 2 的数据的文档
db.class1.find({hobby:{$type:2}},{_id:0})
数据类型对照:
https://docs.mongodb.com/manual/reference/operator/query/type/
进一步的信息筛选
distinct()
功能 : 查看一个集合中某个域值的覆盖范围
e.g. 查看集合中age域的值都有哪些
db.class0.distinct('age')
pretty()
功能 : 将查询结果格式化显示
e.g. db.class0.find().pretty()
limit(n)
功能: 查询结果显示前 n条
e.g. 查询结果显示前3个
db.class0.find({},{_id:0}).limit(3)
skip(n)
功能 : 显示时跳过前n条
e.g. 显示时跳过前三条
db.class0.find({},{_id:0}).skip(3)
count()
功能 :对查找结果计数统计
e.g. 统计sex 为 m的文档数量
db.class0.find({sex:'m'},{_id:0}).count()
sort({键:1/-1})
功能 : 对查找结果排序
1 表示按照升序排列, -1 表示按照降序排列
对查找结果按照年龄升序排列
db.class0.find({age:{$exists:true}},{_id:0}).sort({age:1})
复合排序 : 当第一排序项相同的时候,按照第二排序项排序
db.class0.find({age:{$exists:true}},{_id:0}).sort({age:1,name:-1})
函数的连续使用
获取集合中年龄最小的三个文档
db.class0.find({},{_id:0}).sort({age:1}).limit(3)
删除文档
delete from tableName where ....
db.collectionName.remove(query,justOne)
功能 : 删除指定的文档
参数 : query : 筛选要删除的文档, 类似where子句
用法同 查找操作
justOne :布尔值 默认 false 表示删除所有筛选数据
如果赋值为true 则表示只删除第一条复合的文档
e.g.
db.class0.remove({$or:[{age:{$exists:false}},{age:{$gt:100}}]})
删除第一个复合条件的文档
db.class0.remove({sex:{$exists:false}},true)
删除集合中所有文档
db.collectionName.remove({})
练习:
1. 创建一个数据库 名字grade
use grade
2. 数据库中创建一个集合名字 class
3. 集合中插入若干数据 文档格式如下
{name:'zhang',age;10,sex:'m',hobby:['a','b','c']}
hobby: draw sing dance basketball football pingpong
computer
db.class.insert([
{name:"zhang",age:10,sex:'m',hobby:['a','b','c']},
.....
])
4. 查找练习
查看班级所有人信息
find()
查看班级中年龄为8岁的学生信息
find({age:8})
查看年龄大于10岁的学生信息
find({age:{$gt:10}})
查看年龄在 4---8岁之间的学生信息
find({age:{$gte:4,$lte:8}})
找到年龄为6岁且为男生的学生
find({age:6,sex:'m'})
找到年龄小于7岁或者大于10岁的学生
find({$or:[age:{$lt:7},age:{$gt:10}]})
找到年龄是8岁或者11岁的学生
find({age:{$in:[8,11]}})
找到兴趣爱好有两项的学生
find({hobby:{$size:2}})
找到兴趣爱好有draw的学生
find({hobby:"draw"})
找到既喜欢画画又喜欢跳舞的学生
find({hobby:{$all:["draw","dance"]}})
统计爱好有三项的学生人数
find({hobby:{$size:3}}).count()
找出本班年龄第二大的学生
find().sort({age:-1}).skip(1).limit(1)
查看学生的兴趣范围
db.class.distinct('hobby')
将学生按年龄排序找到年龄最大的三个
find().sort({age:-1}).limit(3)
删除所有 年级大于12或者小于4岁的学生
remove({$or:[{age:{$gt:12}},{age:{$lt:4}}]})
作业 : 复习 数据的查找 和删除操作
mongo练习
*********************************************************
第三天
查找 find(query,field)
findOne()
操作符 : 比较 $lt $lte $gt $gte $eq $ne $in $nin
逻辑 $and $or $not $nor
数组 $all $size
其他 $exists $type $mod
查找函数 : limit() skip() sort() count() pretty()
其他函数 distinct() getCollection()
删除 remove(query,justOne)
=======================================
修改数据
update tableName set ... where .....
db.collectionName.update(query,update,upsert,multi)
功能 : 修改一个文档
参数 : query : 删选要修改的文档 相当于where子句
用法同查找
update : 将数据更新为什么内容 相当于set操作
需要使用修改器操作符
upsert : bool值 默认为false 表示如果query的文档不 存在则无法修改
如果设置为true 表示如果query的文档不存在则根据query和update参数插入新的文档
multi : bool值 默认为false 如果有多条符合筛选条件 的文档则只修改第一条
如果设置为true 则修改所有符合条件的文档
e.g. 将阿红年龄改为24
db.class0.update({name:'阿红'},{$set:{age:24}})
e.g. 如果筛选数据不存在则插入一个新的文档
db.class0.update({name:'阿花'},{$set:{age:18,sex:'w'}},true)
e.g. 可以同时修改多条匹配到的文档
db.class0.update({sex:'w'},{$set:{age:20}},false,true)
修改器操作符
$set
修改一个域的值
增加一个域
e.g. db.class0.update({name:'阿红'},{$set:{sex:'w'}})
$unset
删除一个域
e.g. 删除文档的sex和age域 (后面数字习惯写1,0 都表示删除)
db.class0.update({name:'八戒'},{$unset:{sex:0,age:0}})
$rename
修改一个域的名称
e.g. 修改所有的sex域为gender
db.class0.update({},{$rename:{sex:'gender'}},false,true)
$setOnInsert
如果update操作插入新的文档,则补充插入内容
e.g. 如果插入数据则同时插入sex和tel域内容
db.class0.update({name:'阿华'},{$set:{age:21},$setOnInsert:{sex:'m',tel:'123456'}},true)
$inc
加减修改器
e.g. 年龄减2
db.class0.update({age:{$lt:18}},{$inc:{age:-2}},false,true)
* $inc 可加正数 负数 小数都可以
$mul
乘法修改器
e.g.
db.class0.update({name:'阿华'},{$mul:{age:-0.5}})
* $mul 可乘以正数 负数 小数都可以
$min
设定最小值 : 如果筛选的文档指定的域值小于min值则不修改,如果大于min值则改为min值
e.g.
db.class0.update({},{$min:{age:19}},false,true)
$max
设置最大值 : 如果筛选的文档指定至于大于max值则不变,如果小于max值则修改为max值
e.g.
db.class0.update({},{$max:{age:20}},false,true)
数组修改器
$push 向数组中添加一项
e.g.
db.class1.update({name:"Abby"},{$push:{score:30}})
$pushAll 向数组中添加多项
e.g.
db.class1.update({name:"Jame"},{$pushAll:{score:[10,20]}})
$each 逐个操作
e.g. 利用each添加多项
db.class1.update({name:"Lily"},{$push:{score:{$each:[10,5]}}})
$position
选择数据位置进行操作 必须和each合用
e.g.
db.class1.update({name:"Lucy"},{$push:{score:{$each:[10,10],$position:1}}})
$sort
对数组进行排序 必须和each合用
e.g.
db.class1.update({name:"Lily"},{$push:{score:{$each:[],$sort:1}}})
$pull 从数组中删除一个元素
e.g.
db.class1.update({name:'Lucy'},{$pull:{score:10}})
$pullAll 从数组中删除多个元素
e.g.
db.class1.update({name:'Jame'},{$pullAll:{score:[10,20]}})
$pop 弹出数组中的一项
e.g.
db.class1.update({name:'Lily'},{$pop:{score:-1}})
* -1表示弹出数组中的第一项 1 表示弹出最后一项
$addToSet 向数组中插入一个元素,但是该元素不能和其他元素重复
e.g. 如果已经存在66则无法插入,如果不存在则插入66
db.class1.update({name:'Lily'},{$addToSet:{score:66}})
数据类型补充
时间类型
mongo中存储时间的格式 :ISODate
方法1 自动生成当前时间
db.class2.insert({title:'Python入门',date:new Date()})
方法2 生成当前时间
db.class2.insert({title:'Python精通',date:ISODate()})
方法3 将生成时间变为字符串存储
db.class2.insert({title:'Python AI',date:Date()})
指定时间的转换
ISOData()
功能 : 生成mongo时间类型
参数 : 如果不加参数则生成当前时间
参数格式 "2018-11-11 11:11:11"
"20180101 11:11:11"
"20181102"
e.g.
db.class2.insert({title:'Python 爬虫',date:ISODate("20180101 11:11:11")})
时间戳获取
e.g.
db.class2.insert({title:'PythonWeb',date:ISODate().valueOf()})
null
1. 如果某个域存在却没有值可以设置为null
e.g. db.class2.insert({title:'Python 秘籍',price:null})
2.表示某个域不存在可以通过null进行匹配
e.g. db.class2.find({date:null},{_id:0})
可以查找到date不存在的文档
Object类型 (值是一个文档)
*当使用外层文档引用内部文档的时候可以用用 . 的方法引用
在使用时需要加上引号
e.g.
db.class2.find({'publication.publisher':'人民教育'},{_id:0})
e.g.
db.class2.update({title:'Python数据'},{$set:{'publication.price':58.8}})
数组的下标引用
使用一个数组时,可以使用 .序列下标 的方式使用数组具体的某一项。同样需要用引号
e.g. db.class1.update({name:'Lily'},{$set:{'score.0':60}})
e.g. db.class1.find({'score.0':{$gt:90}})
文档查找结果的有序性
可以通过[]取查找结果序列的某一项
db.class1.find({},{_id:0})[1]
练习 :
使用之前的grade数据库
1. 将小红的年龄变为8岁 兴趣爱好变为 跳舞 画画
{$set:{age:8,hobby:['dance','draw']}}
2. 追加小明兴趣爱好 唱歌
{$push:{hobby:'sing'}}
3. 小王兴趣爱好增加 吹牛 打篮球
{$pushAll:{hobby:['吹牛','basketball']}}
4. 小李增加爱好,跑步和唱歌,但是不要和以前的重复
{$addToSet:{hobby:{$each:['running','sing']}}}
5. 该班所有同学年龄加1
update({},{$inc:{age:1}},false,true)
6. 删除小明的sex属性
{$unset:{sex:0}}
7. 删除小李兴趣中的第一项
{$pop:{hobby:-1}}
8. 将小红兴趣中的画画爱好删除
{$pull:{hobby:'draw'}}
索引
指的是建立指定键值及所在文档中存储位置的对照清单。使用索引可以方便我们进行快速查找,减少遍历次数,提高查找效率
mongo中如何创建索引
ensureIndex()
功能 : 创建索引
参数 : 索引类别,索引选项
e.g.
db.class0.ensureIndex({'name':1})
* 1表示为该域创建正向索引,-1 表示逆向索引
* _id 域会自动创建索引
查看一个集合中的索引
db.class0.getIndexes()
删除索引
dropIndex()
功能 : 删除索引
参数 : 删除索引的名称
e.g. 可以通过索引名称或者索引键值对删除
db.class0.dropIndex('name_1')
db.class0.dropIndex({name:1})
dropIndexes()
功能 : 删除所有索引
e.g. db.class0.dropIndexes()
索引类型
复合索引
根据多个域创建一个索引
db.class0.ensureIndex({name:1,age:-1})
数组索引
如果对某个数组域创建索引,那么表示对数组中的每个值均创建了索引,通过数组中单个值查询,也是索引查询
db.class1.ensureIndex({'score':1})
子文档索引
如果对一个域创建索引,值是一个文档则子文档也会同时形成索引
如果对子文档某一个域进行索引创建,则只有通过子文档中的该域查找时为索引查找
e.g.
db.class2.ensureIndex({'publication.pulisher':1})
覆盖索引
查找时只获取索引项的内容,而不必去获取原数据中的其他内容,这样就不去连接原来的数据直接返回即可
e.g. name为索引项,显示也只要name域
db.class0.find({name:'Lily'},{_id:0,name:1})
唯一索引
创建索引时希望索引域的值均不相同,也可以据此限制一个域的值
e.g.
db.class0.ensureIndex({name:1},{'unique':true})
*当对某个域创建了唯一索引后,即不允许在插入相同的值的文档
稀疏索引(间隙索引)
只针对有指定域的文档创建索引表,没有该域的文档,不会插入到索引表中
e.g.
db.class2.ensureIndex({'date':1},{sparse:true})
索引约束 :
1.影响数据的插入,删除,修改操作。当数据发生改变时,索引表必须同步更新
2.索引也是需要占用一定的空间资源
综上 : 当数据库大量的操作是插入,修改,删除操作,而非查询操作时,不适合创建索引。数据量比较小时,考虑到空间成本也不适合创建索引。即使适合创建索引的情况,也不是索引越多越好。
聚合
多数据文档进行整理统计
db.collectionName.aggregate()
功能 : 聚合函数,配合聚合条件进行数据整理统计
参数 : 聚合条件
聚合操作符
$group 分组 和分组操作符配合使用确定按什么分组
++++++++++++++++++++++++++++++++++
分组操作符 (和$group配合)
$sum 求和
统计每组个数
db.class0.aggregate({$group:{_id:'$gender',num:{$sum:1}}})
聚合 分组 按gender分组 统计结果名
统计每组年龄和
db.class0.aggregate({$group:{_id:'$gender',num:{$sum:'$age'}}})
$avg 求平均数
求平均年龄
db.class0.aggregate({$group:{_id:'$gender',num:{$avg:'$age'}}})
$min 求最小值
求每组姓名的最小值
db.class0.aggregate({$group:{_id:'$gender',name:{$min:'$name'}}})
$max
求每组姓名的最大值
db.class0.aggregate({$group:{_id:'$gender',name:{$max:'$name'}}})
$first
返回每组第一个文档指定域值
db.class0.aggregate({$group:{_id:'$gender',name:{$first:'$name'}}})
$last
返回每组最后一个文档指定域值
db.class0.aggregate({$group:{_id:'$gender',name:{$last:'$name'}}})
+++++++++++++++++++++++++++++++++++
$project
用于修饰文档的显示结构
e.g.
db.class0.aggregate({$project:{_id:0,name:1,age:1}})
e.g.
db.class0.aggregate({$project:{_id:0,Name:'$name',Age:'$age'}})
$match 过滤数据
操作符的值同find的query
db.class0.aggregate({$match:{name:{$gt:'Tom'}}})
$skip 跳过前几条文档
db.class0.aggregate({$skip:2})
$limit 显示几条文档
db.class0.aggregate({$limit:2})
$sort 排序
db.class0.aggregate({$sort:{name:1}})
聚合管道
将前一个聚合操作的结果给下一个聚合操作继续执行
db.collectionName.aggregate([聚合1,聚合2,.....])
e.g. match---> project ---> sort
db.class0.aggregate([{$match:{name:{$gt:'Tom'}}},{$project:{_id:0,name:1,age:1}},{$sort:{name:-1}}])
e.g. group ---> match
db.class0.aggregate([{$group:{_id:'$gender',num:{$sum:1}}},{$match:{$nor:[{_id:'m'},{_id:'w'}]}}])
作业练习 :
使用之前的grade数据库
增加分数域 score:{'chinese':88,'english':78,'math':98}
1. 按照性别分组统计每组人数
aggregate({$group:{_id:'$sex',num:{$sum:1}}})
2. 按照姓名分组,过滤出有重名的同学
aggregate([{$group:{_id:'$name',num:{$sum:1}}},{$match:{num:{$gt:1}}}])
3. 统计每名男生的语文成绩
aggregate([{$match:{sex:'m'}},{$project:{_id:0,name:1,'score.chinese':1}}])
4. 将女生按照英语分数降序排列
aggregate([{$match:{sex:'w'}},{$sort:{'score.english':-1}}])
******************************************************
第四天
修改
update(query,update,upsert,multi)
修改器 : $set $unset $rename $setOnInsert $inc $mul
$min $max
$push $pushAll $each $pull $pullAll $position
$pop $addToSet $sort
数据类型 Date() ISODate() valueOf()
null 的使用
Object :通过 . 取内部文档
通过 . 取数组索引
索引创建 ensureIndex()
聚合操作 aggregate()
聚合操作符 $group $match $project $limit $skip $sort
========================================================
固定集合
mongo中可以创建大小固定的集合,称之为固定集合,固定集合的性能出色,适用于很多场景
比如 : 日志处理, 临时缓存
特点 : 插入速度快
顺序查询速度快
能够淘汰早期数据
可以控制集合空间
创建:
db.createCollection(collectionName,{capped:true,size:10000,max:1000})
size :设置固定集合的大小 kb
max : 最多能容纳多少文档
e.g.
创建一个最多包含三条文档的集合
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
数据库 要存储的文件
*如果数据库不存在则自动创建
fs.files
{ "_id" : ObjectId("5b0770c169d72e1e3a6eebda"), "chunkSize" : 261120, "uploadDate" : ISODate("2018-05-25T02:11:13.986Z"), "length" : 8313457, "md5" : "4b39deb86dcb6ece44ef52a69dcd6e1a", "filename" : "xly.zip" }
fs.chunks
{ "_id" : ObjectId("5b0770c169d72e1e3a6eebee"), "files_id" : ObjectId("5b0770c169d72e1e3a6eebda"), "n" : 19, "data" : BinData(0,"wGTrj3......)}
获取数据库中文件
mongofiles -d grid get xly.zip
优缺点 :
优点 : 存储方便,方便数据库移植,对文件个数没有太多限制
缺点 : 读写效率低
游标
为什么使用游标
1. 防止网络拥塞,造成数据传输慢
2. 提高用户解析体验,可以后端解析
var cursor = db.class0.find() 创建游标
cursor.hasNext() 查看是否有下一个数据
cursor.next() 获取下一个数据
通过Python 操作mongodb数据库
Python ---》 mongodb编程接口 pymongo
安装
sudo pip3 install pymongo
操作步骤
1. 创建mongo数据库的链接对象
conn = MongoClient('localhost',27017)
2. 生成数据库对象
db = conn.stu
3. 生成集合对象
my_set = db.class0
4. 增删改差索引聚合操作
插入数据 insert() insert_many() insert_one()
save()
删除数据
remove({},multi = True)
multi 默认为True 表示删除所有符合条件的数据
设置为False 表示只删除一条
数据查找
find()
功能 : 查找数据库内容
参数 : 同 mongo shell find()
返回值 : 返回一个游标 ---》 迭代器
cursor 可迭代对象属性函数
next()
count()
limit()
skip()
sort()
mongoshell ---> sort({'name':1})
pymongo ---> sort([('name',1)])
* 进行排序时游标要确保没有被访问过
find_one()
返回值是一个字典
修改操作
update()
参数和mongoshell 中 update相同
update_many() :匹配到多个文档时全部修改
update_one() : 只修改匹配到的第一条文档
* 变成中mongo的数据类型null 可以用Python中的 None替代
索引
创建索引
ensure_index()
create_index()
create_indexes() 创建多个索引
查看集合中的索引
list_indexes()
删除索引
drop_index() 删除某一个索引
drop_indexes() 删除所有索引
聚合操作
aggregate([])
参数 : 与mongoshell中聚合参数写法一致
返回值 : 迭代器 同find的返回值