数据库 Mysql-mongodb-redis

时间:2022-03-11 00:59:05

目录

  • 数据库系统解决的问题:持久化存储,优化读写,保证数据的有效性
  • 当前使用的数据库,主要分为两类
    • 文档型,如sqlite,就是一个文件,通过对文件的复制完成数据库的复制
    • 服务型,如mysql、postgre,数据存储在一个物理文件中,但是需要使用终端以tcp/ip协议连接,进行数据库的读写操作

1. Mysql

1.1. 介绍

1.1.1 基础

E-R模型

  • 当前物理的数据库都是按照E-R模型进行设计的
  • E表示entry,实体
  • R表示relationship,关系
  • 一个实体转换为数据库中的一个表
  • 关系描述两个实体之间的对应规则,包括
  • 一对一
  • 一对多
  • 多对多
  • 关系转换为数据库表中的一个列 *在关系型数据库中一行就是一个对象

三范式
经过研究和对使用中问题的总结,对于设计数据库提出了一些规范,这些规范被称为范式
第一范式(1NF):列不可拆分
第二范式(2NF):唯一标识
第三范式(3NF):引用主键
说明:后一个范式,都是在前一个范式的基础上建立的

数据完整性

  • 一个数据库就是一个完整的业务单元,可以包含多张表,数据被存储在表中
  • 在表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表的时候,为表添加一些强制性的验证,包括数据字段的类型、约束

字段类型
在mysql中包含的数据类型很多,这里主要列出来常用的几种

  • 数字:int,decimal
  • 字符串:varchar,text
  • 日期:datetime
  • 布尔:bit

约束

  • 主键primary key
  • 非空not null
  • 惟一unique
  • 默认default
  • 外键foreign key
  1. 主键的名称一般为id,设置为int型,无符号数,自动增长,非空
  2. 自动增长表示由mysql系统负责维护这个字段的值,不需要手动维护,所以不用关心这个字段的具体值
  3. 字符串varchar类型需要设置长度,即最多包含多少个字符

    1.1.2 配置

    安装
    sudo apt-get install mysql-server mysql-client
    启动
    service mysql start
    停止
    service mysql stop
    重启
    service mysql restart
    允许远程连接
    找到mysql配置文件并修改
    sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
    bind-address=127.0.0.1注释
    登录mysql,运行命令
    grant all privileges on *.* to ‘root‘@‘%‘ identified by ‘mysql‘ with grant option;
    flush privileges;
    重启mysql

命令行连接
mysql -uroot -p
回车后输入密码
退出:quit
查看版本:select version();
显示当前时间:select now();

远程连接
mysql -hip地址 -uroot -p
-h后面写要连接的主机ip地址
-u后面写连接的用户名
-p回车后写密码

1.1.3 数据库操作

创建数据库
create database 数据库名 charset=utf8;
删除数据库
drop database 数据库名;
切换数据库
use 数据库名;
查看当前选择的数据库
select database();

表操作
查看当前数据库中所有表
show tables;
创建表
auto_increment表示自动增长

create table 表名(列及类型);
如:
create table students(
id int auto_increment primary key,
sname varchar(10) not null
);

修改表

alter table 表名 add|change|drop 列名 类型;
如:
alter table students add birthday datetime;

删除表
drop table 表名;
查看表结构
desc 表名;
更改表名称
rename table 原表名 to 新表名;
查看表的创建语句
show create table ‘表名‘;

数据操作
查询
select * from 表名
增加
全列插入:insert into 表名 values(...)
缺省插入:insert into 表名(列1,...) values(值1,...)
同时插入多条数据:insert into 表名 values(...),(...)...;
或insert into 表名(列1,...) values(值1,...),(值1,...)...;

主键列是自动增长,但是在全列插入时需要占位,通常使用0,插入成功后以实际数据为准
修改
update 表名 set 列1=值1,... where 条件
删除
delete from 表名 where 条件
逻辑删除,本质就是修改操作update

alter table students add isdelete bit default 0;
如果需要删除则
update students isdelete=1 where ...;

备份与恢复

数据备份

进入超级管理员
sudo -s
进入mysql库目录
cd /var/lib/mysql
运行mysqldump命令
mysqldump –uroot –p 数据库名 > ~/Desktop/备份文件.sql; 按提示输入mysql的密码

数据恢复

连接mysqk,创建数据库

退出连接,执行如下命令

mysql -uroot –p 数据库名 < ~/Desktop/备份文件.sql
根据提示输入mysql密码

1.2. 查询

查询的基本语法
select * from 表名;

  • from关键字后面写表名,表示数据来源于是这张表
  • select后面写表中的列名,如果是*表示在结果中显示表中所有列
  • 在select后面的列名部分,可以使用as为列起别名,这个别名出现在结果集中
  • 如果要查询多个列,之间使用逗号分隔

消除重复行

  • 在select后面列前使用distinct可以消除重复的行
    select distinct gender from students;

1.2.1 条件

使用where子句对表中的数据筛选,结果为true的行会出现在结果集中
语法如下:
select * from 表名 where 条件;

比较运算符
等于=
大于>
大于等于>=
小于<
小于等于<=
不等于!=或<>
查询编号大于3的学生
select * from students where id>3;
查询编号不大于4的科目
select * from subjects where id<=4;
查询姓名不是“黄蓉”的学生
select * from students where sname!=‘黄蓉‘;
查询没被删除的学生
select * from students where isdelete=0;

逻辑运算符
and
or
not
查询编号大于3的女同学
select * from students where id>3 and gender=0;
查询编号小于4或没被删除的学生
select * from students where id<4 or isdelete=0;

模糊查询
like
%表示任意多个任意字符
_表示一个任意字符
查询姓黄的学生
select * from students where sname like ‘黄%‘;
查询姓黄并且名字是一个字的学生
select * from students where sname like ‘黄_‘;
查询姓黄或叫靖的学生
select * from students where sname like ‘黄%‘ or sname like ‘%靖%‘;

范围查询
in表示在一个非连续的范围内
查询编号是1或3或8的学生
select * from students where id in(1,3,8);
between ... and ...表示在一个连续的范围内
查询学生是3至8的学生
select * from students where id between 3 and 8;
查询学生是3至8的男生
select * from students where id between 3 and 8 and gender=1;

空判断
注意:null与‘‘是不同的
判空is null
查询没有填写地址的学生
select * from students where hometown is null;
判非空is not null
查询填写了地址的学生
select * from students where hometown is not null;
查询填写了地址的女生
select * from students where hometown is not null and gender=0;

优先级
小括号,not,比较运算符,逻辑运算符
and比or先运算,如果同时出现并希望先算or,需要结合()使用

1.2.2 聚合

为了快速得到统计数据,提供了5个聚合函数
count(*)表示计算总行数,括号中写星与列名,结果是相同的
查询学生总数
select count(*) from students;
max(列)表示求此列的最大值
查询女生的编号最大值
select max(id) from students where gender=0;
min(列)表示求此列的最小值
查询未删除的学生最小编号
select min(id) from students where isdelete=0;
sum(列)表示求此列的和
查询男生的编号之后
select sum(id) from students where gender=1;
avg(列)表示求此列的平均值
查询未删除女生的编号平均值
select avg(id) from students where isdelete=0 and gender=0;

1.2.3 分组

按照字段分组,表示此字段相同的数据会被放到一个组中
分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中
可以对分组后的数据进行统计,做聚合运算
语法:
select 列1,列2,聚合... from 表名 group by 列1,列2,列3...
查询男女生总数
select gender as 性别,count(*)
from students
group by gender;
查询各城市人数
select hometown as 家乡,count(*)
from students
group by hometown;

分组后的数据筛选
语法:
select 列1,列2,聚合... from 表名
group by 列1,列2,列3...
having 列1,...聚合...
having后面的条件运算符与where的相同
查询男生总人数
方案一
select count(*)
from studentswhere gender=1;`

方案二:
select gender as 性别,count(*)
from students
group by gender
having gender=1;

对比where与having
where是对from后面指定的表进行数据筛选,属于对原始数据的筛选
having是对group by的结果进行筛选

1.2.4 排序

为了方便查看数据,可以对数据进行排序
语法:
select * from 表名
order by 列1 asc|desc,列2 asc|desc,...
将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推
默认按照列值从小到大排列
asc从小到大排列,即升序
desc从大到小排序,即降序
查询未删除男生学生信息,按学号降序
select * from students
where gender=1 and isdelete=0
order by id desc;
查询未删除科目信息,按名称升序
select * from subject
where isdelete=0
order by stitle;

1.2.4 分页

获取部分行
当数据量过大时,在一页中查看数据是一件非常麻烦的事情
语法
select * from 表名
limit start,count
从start开始,获取count条数据
start索引从0开始

示例:分页
已知:每页显示m条数据,当前显示第n页
求总页数:此段逻辑后面会在python中实现

  • 查询总条数p1
  • 使用p1除以m得到p2
  • 如果整除则p2为总数页
  • 如果不整除则p2 1为总页数

求第n页的数据
select * from students
where isdelete=0
limit (n-1)*m,m

1.3. 高级

实体与实体之间有3种对应关系,这些关系也需要存储下来
在开发中需要对存储的数据进行一些处理,用到内置的一些函数
视图用于完成查询语句的封装
事务可以保证复杂的增删改操作有效

1.3.1 关系

数据库 Mysql-mongodb-redis

创建表的语句如下
create table scores( id int primary key auto_increment, stuid int, subid int, score decimal(5,2) );

外键

思考:怎么保证关系列数据的有效性呢?任何整数都可以吗?
答:必须是学生表中id列存在的数据,可以通过外键约束进行数据的有效性验证
为stuid添加外键约束
alter table scores add constraint stu_sco foreign key(stuid) references students(id);
此时插入或者修改数据时,如果stuid的值在students表中不存在则会报错
在创建表时可以直接创建约束
create table scores( id int primary key auto_increment, stuid int, subid int, score decimal(5,2), foreign key(stuid) references students(id), foreign key(subid) references subjects(id) );

外键的级联操作
在删除students表的数据时,如果这个id值在scores中已经存在,则会抛异常
推荐使用逻辑删除,还可以解决这个问题
可以创建表时指定级联操作,也可以在创建表后再修改外键的级联操作
语法
alter table scores add constraint stu_sco foreign key(stuid) references students(id) on delete cascade;
级联操作的类型包括:

  • restrict(限制):默认值,抛异常
  • cascade(级联):如果主表的记录删掉,则从表中相关联的记录都将被删除
  • set null:将外键设置为空
  • no action:什么都不做

1.3.2 连接

连接查询
连接查询分类如下:

  • 表A inner join 表B:表A与表B匹配的行会出现在结果中
  • 表A left join 表B:表A与表B匹配的行会出现在结果中,外加表A中独有的数据,未对应的数据使用null填充
  • 表A right join 表B:表A与表B匹配的行会出现在结果中,外加表B中独有的数据,未对应的数据使用null填充

在查询或条件中推荐使用“表名.列名”的语法
如果多个表中列名不重复可以省略“表名.”部分
如果表的名称太长,可以在表名后面使用‘ as 简写名‘或‘ 简写名‘,为表起个临时的简写名称
练习
查询学生的姓名、平均分
select students.sname,avg(scores.score) from scores inner join students on scores.stuid=students.id group by students.sname;
查询男生的姓名、总分
select students.sname,avg(scores.score) from scores inner join students on scores.stuid=students.id where students.gender=1 group by students.sname;
查询科目的名称、平均分
select subjects.stitle,avg(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
group by subjects.stitle;
查询未删除科目的名称、最高分、平均分
select subjects.stitle,avg(scores.score),max(scores.score) from scores inner join subjects on scores.subid=subjects.id where subjects.isdelete=0 group by subjects.stitle;

1.3.3 自连接

设计省信息的表结构provinces

  • id
  • ptitle

设计市信息的表结构citys

  • id
  • ctitle
  • proid

citys表的proid表示城市所属的省,对应着provinces表的id值
问题:能不能将两个表合成一张表呢?
思考:观察两张表发现,citys表比provinces表多一个列proid,其它列的类型都是一样的
意义:存储的都是地区信息,而且每种信息的数据量有限,没必要增加一个新表,或者将来还要存储区、乡镇信息,都增加新表的开销太大
答案:定义表areas,结构如下

  • id
  • atitle
  • pid

因为省没有所属的省份,所以可以填写为null
城市所属的省份pid,填写省所对应的编号id
这就是自关联,表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一样的,城市信息的pid引用的是省信息的id
在这个表中,结构不变,可以添加区县、乡镇街道、村社区等信息

创建areas表的语句如下:
create table areas( id int primary key, atitle varchar(20), pid int, foreign key(pid) references areas(id) );

从sql文件中导入数据
source areas.sql;

查询一共有多少个省
查询省的名称为“山西省”的所有城市
select city.* from areas as city inner join areas as province on city.pid=province.id where province.atitle=‘山西省‘;

查询市的名称为“广州市”的所有区县
select dis.*,dis2.* from areas as dis inner join areas as city on city.id=dis.pid left join areas as dis2 on dis.id=dis2.pid where city.atitle=‘广州市‘;

1.3.4 子查询

查询支持嵌套使用
查询各学生的语文、数学、英语的成绩
select sname, (select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle=‘语文‘ and stuid=stu.id) as 语文, (select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle=‘数学‘ and stuid=stu.id) as 数学, (select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle=‘英语‘ and stuid=stu.id) as 英语 from students stu

1.3.5 内置函数

字符串函数
查看字符的ascii码值ascii(str),str是空串时返回0

select ascii('a');

查看ascii码值对应的字符char(数字)

select char(97);

拼接字符串concat(str1,str2...)

select concat(12,34,'ab');

包含字符个数length(str)

select length('abc');

截取字符串

  • left(str,len)返回字符串str的左端len个字符
  • right(str,len)返回字符串str的右端len个字符
  • substring(str,pos,len)返回字符串str的位置pos起len个字符
    select substring(‘abc123‘,2,3);

去除空格

  • ltrim(str)返回删除了左空格的字符串str
  • rtrim(str)返回删除了右空格的字符串str
  • trim([方向 remstr fromstr)返回从某侧删除remstr后的字符串str,方向词包括both、leading、trailing,表示两侧、左、右
select trim('  bar   ');
select trim(leading 'x' FROM 'xxxbarxxx');
select trim(both 'x' FROM 'xxxbarxxx');
select trim(trailing 'x' FROM 'xxxbarxxx');

返回由n个空格字符组成的一个字符串space(n)
select space(10);
替换字符串replace(str,from_str,to_str)
select replace(‘abc123‘,‘123‘,‘def‘);
大小写转换,函数如下

  • lower(str)
  • upper(str)

select lower(‘aBcD‘);

数学函数
求绝对值abs(n)
select abs(-32);
求m除以n的余数mod(m,n),同运算符%
select mod(10,3); select 10%3;
地板floor(n),表示不大于n的最大整数
select floor(2.3);
天花板ceiling(n),表示不小于n的最大整数
select ceiling(2.3);
求四舍五入值round(n,d),n表示原数,d表示小数位置,默认为0
select round(1.6);
求x的y次幂pow(x,y)
select pow(2,3);
获取圆周率PI()
select PI();
随机数rand(),值为0-1.0的浮点数
select rand();
还有其它很多三角函数,使用时可以查询文档

日期时间函数
获取子值,语法如下

  • year(date)返回date的年份(范围在1000到9999)
  • month(date)返回date中的月份数值
  • day(date)返回date中的日期数值
  • hour(time)返回time的小时数(范围是0到23)
  • minute(time)返回time的分钟数(范围是0到59)
  • second(time)返回time的秒数(范围是0到59)

select year(‘2016-12-21‘);

日期计算,使用 -运算符,数字后面的关键字为year、month、day、hour、minute、second
select ‘2016-12-21‘ interval 1 day;
日期格式化date_format(date,format),format参数可用的值如下

获取年%Y,返回4位的整数

* 获取年%y,返回2位的整数

* 获取月%m,值为1-12的整数

获取日%d,返回整数

* 获取时%H,值为0-23的整数

* 获取时%h,值为1-12的整数

* 获取分%i,值为0-59的整数

* 获取秒%s,值为0-59的整数

select date_format(‘2016-12-21‘,‘%Y %m %d‘);
当前日期current_date()
select current_date();
当前时间current_time()
select current_time();
当前日期时间now()
select now();

1.3.6 视图

对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情
解决:定义视图
视图本质就是对查询的一个封装
定义视图
create view stuscore as select students.*,scores.score from scores inner join students on scores.stuid=students.id;
视图的用途就是查询
select * from stuscore;

1.3.7 事务

当一个业务逻辑需要多个sql完成时,如果其中某条sql语句出错,则希望整个操作都退回
使用事务可以完成退回的功能,保证业务逻辑的正确性

事务四大特性(简称ACID)

  • 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行
  • 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
  • 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的
  • 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障

要求:表的类型必须是innodb或bdb类型,才可以对此表使用事务

查看表的创建语句
show create table students;
修改表的类型
alter table ‘表名‘ engine=innodb;
事务语句
开启begin; 提交commit; 回滚rollback;

1.4. 与python交互

1.4.1 交互类型

安装引入模块
sudo apt-get install python-mysql
在文件中引入模块
import Mysqldb

Connection对象

用于建立与数据库的连接
创建对象:调用connect()方法
conn=connect(参数列表)
参数host:连接的mysql主机,如果本机是‘localhost‘
参数port:连接的mysql主机的端口,默认是3306
参数db:数据库的名称
参数user:连接的用户名
参数password:连接的密码
参数charset:通信采用的编码方式,默认是‘gb2312‘,要求与数据库创建时指定的编码一致,否则中文会乱码

对象的方法

close()关闭连接
commit()事务,所以需要提交才会生效
rollback()事务,放弃之前的操作
cursor()返回Cursor对象,用于执行sql语句并获得结果

Cursor对象

执行sql语句
创建对象:调用Connection对象的cursor()方法
cursor1=conn.cursor()

对象的方法
close()关闭
execute(operation [, parameters ])执行语句,返回受影响的行数
fetchone()执行查询语句时,获取查询结果集的第一个行数据,返回一个元组
next()执行查询语句时,获取当前行的下一行
fetchall()执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回
scroll(value[,mode])将行指针移动到某个位置

  • mode表示移动的方式
  • mode的默认值为relative,表示基于当前行移动到value,value为正则向下移动,value为负则向上移动
  • mode的值为absolute,表示基于第一条数据的位置,第一条数据的位置为0

对象的属性
rowcount只读属性,表示最近一次execute()执行后受影响的行数
connection获得当前连接对象

1.4.2 增改删

增加
创建testInsert.py文件,向学生表中插入一条数据

#encoding=utf-8
import MySQLdb
try:
    conn=MySQLdb.connect(host='localhost',port=3306,db='test1',user='root',passwd='mysql',charset='utf8')
    cs1=conn.cursor()
    count=cs1.execute("insert into students(sname) values('张良')")
    print count
    conn.commit()
    cs1.close()
    conn.close()
except Exception,e:
    print e.message

修改
创建testUpdate.py文件,修改学生表的一条数据

#encoding=utf-8
import MySQLdb
try:
    conn=MySQLdb.connect(host='localhost',port=3306,db='test1',user='root',passwd='mysql',charset='utf8')
    cs1=conn.cursor()
    count=cs1.execute("update students set sname='刘邦' where id=6")
    print count
    conn.commit()
    cs1.close()
    conn.close()
except Exception,e:
    print e.message

删除
创建testDelete.py文件,删除学生表的一条数据

#encoding=utf-8
import MySQLdb
try:
    conn=MySQLdb.connect(host='localhost',port=3306,db='test1',user='root',passwd='mysql',charset='utf8')
    cs1=conn.cursor()
    count=cs1.execute("delete from students where id=6")
    print count
    conn.commit()
    cs1.close()
    conn.close()
except Exception,e:
    print e.message

sql语句参数化
创建testInsertParam.py文件,向学生表中插入一条数据

#encoding=utf-8
import MySQLdb
try:
    conn=MySQLdb.connect(host='localhost',port=3306,db='test1',user='root',passwd='mysql',charset='utf8')
    cs1=conn.cursor()
    sname=raw_input("请输入学生姓名:")
    params=[sname]
    count=cs1.execute('insert into students(sname) values(%s)',params)
    print count
    conn.commit()
    cs1.close()
    conn.close()
except Exception,e:
    print e.message

其它语句
cursor对象的execute()方法,也可以用于执行create table等语句
建议在开发之初,就创建好数据库表结构,不要在这里执行

1.4.3 查询

查询一行数据
创建testSelectOne.py文件,查询一条学生信息

#encoding=utf8
import MySQLdb
try:
    conn=MySQLdb.connect(host='localhost',port=3306,db='test1',user='root',passwd='mysql',charset='utf8')
    cur=conn.cursor()
    cur.execute('select * from students where id=7')
    result=cur.fetchone()
    print result
    cur.close()
    conn.close()
except Exception,e:
    print e.message

查询多行数据
创建testSelectMany.py文件,查询一条学生信息

#encoding=utf8
import MySQLdb
try:
    conn=MySQLdb.connect(host='localhost',port=3306,db='test1',user='root',passwd='mysql',charset='utf8')
    cur=conn.cursor()
    cur.execute('select * from students')
    result=cur.fetchall()
    print result
    cur.close()
    conn.close()
except Exception,e:
    print e.message

2. MongoDB

MongoDB 是一个基于分布式文件存储的NoSQL数据库
由C 语言编写,运行稳定,性能高
旨在为 WEB 应用提供可扩展的高性能数据存储解决方案
查看官方网站

MongoDB特点

模式* :可以把不同结构的文档存储在同一个数据库里
面向集合的存储:适合存储 JSON风格文件的形式
完整的索引支持:对任何属性可索引
复制和高可用性:支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目的是提供冗余及自动故障转移
自动分片:支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器
丰富的查询:支持丰富的查询表达方式,查询指令使用JSON形式的标记,可轻易查询文档中的内嵌的对象及数组
快速就地更新:查询优化器会分析查询表达式,并生成一个高效的查询计划
高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)

2.1. 基本操作

  • MongoDB将数据存储为一个文档,数据结构由键值(key=>value)对组成
  • MongoDB文档类似于JSON对象,字段值可以包含其他文档、数组、文档数组

    SQL术语/概念 MongoDB术语/概念 解释/说明
    database database 数据库
    table collection 数据库表/集合
    row document 数据记录行/文档
    column field 数据字段/域
    index index 索引
    table joins 表连接,MongoDB不支持
    primary key primary key 主键,MongoDB自动将_id字段设置为主键
  • 三元素:数据库,集合,文档
  • 集合就是关系数据库中的表
  • 文档对应着关系数据库中的行
  • 文档,就是一个对象,由键值对构成,是json的扩展Bson形式
    {‘name‘:‘guojing‘,‘gender‘:‘男‘}
  • 集合:类似于关系数据库中的表,储存多个文档,结构不固定,如可以存储如下文档在一个集合中
    {‘name‘:‘guojing‘,‘gender‘:‘男‘} {‘name‘:‘huangrong‘,‘age‘:18} {‘book‘:‘shuihuzhuan‘,‘heros‘:‘108‘}
  • 数据库:是一个集合的物理容器,一个数据库中可以包含多个文档
  • 一个服务器通常有多个数据库

2.1.1 安装

到官网,选择合适的版本下载
解压
tar -zxvf mongodb-linux-x86_64-ubuntu1604-3.4.0.tgz
移动到/usr/local/目录下
sudo mv -r mongodb-linux-x86_64-ubuntu1604-3.4.0/ /usr/local/mongodb
将可执行文件添加到PATH路径中
export PATH=/usr/local/mongodb/bin:$PATH

2.1.2 数据库操作

数据库切换
查看当前数据库名称
db
查看所有数据库名称
列出所有在物理上存在的数据库
show dbs
切换数据库
如果数据库不存在,则指向数据库,但不创建,直到插入数据或创建集合时数据库才被创建
use 数据库名称
默认的数据库为test,如果你没有创建新的数据库,集合将存放在test数据库中

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

2.1.3 集合操作

集合创建
语法
db.createCollection(name, options)
name是要创建的集合的名称
options是一个文档,用于指定集合的配置
选项??参数是可选的,所以只需要到指定的集合名称。以下是可以使用的选项列表:
例1:不限制集合大小
db.createCollection("stu")
例2:限制集合大小,后面学会插入语句后可以查看效果
参数capped:默认值为false表示不设置上限,值为true表示设置上限
参数size:当capped值为true时,需要指定此参数,表示上限大小,当文档达到上限时,会将之前的数据覆盖,单位为字节
db.createCollection("sub", { capped : true, size : 10 } )

查看当前数据库的集合
语法
show collections
删除
语法
db.集合名称.drop()

2.1.4 数据类型

下表为MongoDB中常用的几种数据类型

Object ID:文档ID
String:字符串,最常用,必须是有效的UTF-8
Boolean:存储一个布尔值,true或false
Integer:整数可以是32位或64位,这取决于服务器
Double:存储浮点值
Arrays:数组或列表,多个值存储到一个键
Object:用于嵌入式的文档,即一个值为一个文档
Null:存储Null值
Timestamp:时间戳
Date:存储当前日期或时间的UNIX时间格式

object id
每个文档都有一个属性,为_id,保证每个文档的唯一性
可以自己去设置_id插入文档
如果没有提供,那么MongoDB为每个文档提供了一个独特的_id,类型为objectID
objectID是一个12字节的十六进制数
前4个字节为当前时间戳
接下来3个字节的机器ID
接下来的2个字节中MongoDB的服务进程id
最后3个字节是简单的增量值

2.1.5 数据操作

插入
语法
db.集合名称.insert(document)
插入文档时,如果不指定_id参数,MongoDB会为文档分配一个唯一的ObjectId
例1
db.stu.insert({name:‘gj‘,gender:1})
例2
s1={_id:‘20160101‘,name:‘hr‘} s1.gender=0 db.stu.insert(s1)

简单查询
语法
db.集合名称.find()

更新
语法
db.集合名称.update( <query>, <update>, {multi: <boolean>} )
参数query:查询条件,类似sql语句update中where部分
参数update:更新操作符,类似sql语句update中set部分
参数multi:可选,默认是false,表示只更新找到的第一条记录,值为true表示把满足条件的文档全部更新
例3:全文档更新
db.stu.update({name:‘hr‘},{name:‘mnc‘})
例4:指定属性更新,通过操作符$set
db.stu.insert({name:‘hr‘,gender:0})
db.stu.update({name:‘hr‘},{$set:{name:‘hys‘}})
例5:修改多条匹配到的数据
db.stu.update({},{$set:{gender:0}},{multi:true})

保存
语法
db.集合名称.save(document)
如果文档的_id已经存在则修改,如果文档的_id不存在则添加
例6
db.stu.save({_id:‘20160102‘,‘name‘:‘yk‘,gender:1})
例7
db.stu.save({_id:‘20160102‘,‘name‘:‘wyk‘})

删除
语法
db.集合名称.remove( <query>, { justOne: <boolean> } )
参数query:可选,删除的文档的条件
参数justOne:可选,如果设为true或1,则只删除一条,默认false,表示删除多条
例8:只删除匹配到的第一条
db.stu.remove({gender:0},{justOne:true})
例9:全部删除
db.stu.remove({})

关于size的示例
例10
创建集合
db.createCollection(‘sub‘,{capped:true,size:10})
插入第一条数据库查询
db.sub.insert({title:‘linux‘,count:10}) db.sub.find()
插入第二条数据库查询
db.sub.insert({title:‘web‘,count:15}) db.sub.find()
插入第三条数据库查询
db.sub.insert({title:‘sql‘,count:8}) db.sub.find()
插入第四条数据库查询
db.sub.insert({title:‘django‘,count:12}) db.sub.find()
插入第五条数据库查询
db.sub.insert({title:‘python‘,count:14}) db.sub.find()

2.1.6 数据查询

基本查询
方法find():查询
db.集合名称.find({条件文档})
方法findOne():查询,只返回第一个
db.集合名称.findOne({条件文档})
方法pretty():将结果格式化
db.集合名称.find({条件文档}).pretty()

比较运算符
等于,默认是等于判断,没有运算符
小于$lt
小于或等于$lte
大于$gt
大于或等于$gte
不等于$ne
例1:查询名称等于‘gj‘的学生
db.stu.find({name:‘gj‘})
例2:查询年龄大于或等于18的学生
db.stu.find({age:{$gte:18}})

逻辑运算符
查询时可以有多个条件,多个条件之间需要通过逻辑运算符连接
逻辑与:默认是逻辑与的关系
例3:查询年龄大于或等于18,并且性别为1的学生
db.stu.find({age:{$gte:18},gender:1})
逻辑或:使用$or
例4:查询年龄大于18,或性别为0的学生
db.stu.find({$or:[{age:{$gt:18}},{gender:1}]})
and和or一起使用
例5:查询年龄大于18或性别为0的学生,并且学生的姓名为gj
db.stu.find({$or:[{age:{$gte:18}},{gender:1}],name:‘gj‘})

范围运算符
使用"$in","$nin" 判断是否在某个范围内
例6:查询年龄为18、28的学生
db.stu.find({age:{$in:[18,28]}})

支持正则表达式
使用//或$regex编写正则表达式
例7:查询姓黄的学生
db.stu.find({name:/^黄/}) db.stu.find({name:{$regex:‘^黄‘}}})

自定义查询
使用$where后面写一个函数,返回满足条件的数据
例7:查询年龄大于30的学生
db.stu.find({$where:function(){return this.age>20}})

高级方法

Limit skip 投影 排序 统计个数 消除重复

2.2 高级操作

聚合 aggregate

$group

$match

$project

$sort

$limit 、$skip

$unwind

2.3 与python交互

点击查看官方文档
安装python包
进入虚拟环境
sudo pip install pymongo
或源码安装
python setup.py

引入包pymongo
import pymongo
连接,创建客户端
client=pymongo.MongoClient("localhost", 27017)
获得数据库test1
db=client.test1
获得集合stu
stu = db.stu
添加文档
s1={name:‘gj‘,age:18} s1_id = stu.insert_one(s1).inserted_id
查找一个文档
s2=stu.find_one()
查找多个文档1
for cur in stu.find(): print cur
查找多个文档2
cur=stu.find() cur.next() cur.next() cur.next()
获取文档个数
print stu.count()

3. redis

3.1 安装

下载:打开redis官方网站,推荐下载稳定版本(stable)
解压
tar zxvf redis-3.2.5.tar.gz 复制:推荐放到usr/local目录下sudo mv -r redis-3.2.3/* /usr/local/redis/进入redis目录cd /usr/local/redis/生成sudo make测试sudo make test这段运行时间会较长 安装:将redis的命令安装到/usr/bin/目录sudo make install`

运行
启动服务器:在桌面目录
redis-server 按ctrl c停止
启动客户端:在新终端中运行如下代码
redis-cli
运行命令
ping set ‘a‘ ‘123‘
当添加键值后,发现在当前运行的目录下,创建了一个文件:dump.rdb,这个文件用于将数据持久化存储

3.2 基本配置

在源文件/usr/local/redis目录下,文件redis.conf为配置文件
绑定地址:如果需要远程访问,可将此行注释
bind 127.0.0.1
端口,默认为6379
port 6379
是否以守护进程运行

  • 如果以守护进程运行,则不会在命令行阻塞,类似于服务
  • 如果以非守护进程运行,则当前终端被阻塞,无法使用
  • 推荐改为yes,以守护进程运行

daemonize no|yes
数据文件
dbfilename dump.rdb
数据文件存储路径
dir的默认值为./,表示当前目录 推荐改为:dir /var/lib/redis

使用配置文件方式启动
直接运行redis-server会直接运行,阻塞当前终端
一般配置文件都放在/etc/目录下
sudo cp /usr/local/redis/redis.conf /etc/redis/
推荐指定配置文件启动
sudo redis-server /etc/redis/redis.conf
停止redis服务
ps ajx|grep redis
sudo kill -9 redis的进程id

3.3 数据操作

redis是key-value的数据,所以每个数据都是一个键值对
键的类型是字符串
值的类型分为五种:

  • 字符串string
  • 哈希hash
  • 列表list
  • 集合set
  • 有序集合zset

数据操作的全部命令,可以查看中文网站

3.3.1 string

string是redis最基本的类型
最大能存储512MB数据
string类型是二进制安全的,即可以为任何数据,比如数字、图片、序列化对象等
命令

设置
设置键值
set key value
设置键值及过期时间,以秒为单位
SETEX key seconds value
设置多个键值
MSET key value [key value ...]
获取
根据键获取值,如果不存在此键则返回nil
GET key
根据多个键获取多个值
MGET key [key ...]
运算
要求:值是数字
将key对应的value加1
INCR key
将key对应的value加整数
INCRBY key increment
将key对应的value减1
DECR key
将key对应的value减整数
DECRBY key decrement
其它
追加值
APPEND key value
获取值长度
STRLEN key

3.3.2 键的命令

查找键,参数支持正则
KEYS pattern
判断键是否存在,如果存在返回1,不存在返回0
EXISTS key [key ...]
查看键对应的value的类型
TYPE key
删除键及对应的值
DEL key [key ...]
设置过期时间,以秒为单位
创建时没有设置过期时间则一直存在,直到使用使用DEL移除
EXPIRE key seconds
查看有效时间,以秒为单位
TTL key

3.3.3hash

hash用于存储对象,对象的格式为键值对
命令
设置
设置单个属性
HSET key field value
设置多个属性
HMSET key field value [field value ...]
获取
获取一个属性的值
HGET key field
获取多个属性的值
HMGET key field [field ...]
获取所有属性和值
HGETALL key
获取所有的属性
HKEYS key
返回包含属性的个数
HLEN key
获取所有值
HVALS key
其它
判断属性是否存在
HEXISTS key field
删除属性及值
HDEL key field [field ...]
返回值的字符串长度
HSTRLEN key field

3.3.4 list

列表的元素类型为string
按照插入顺序排序
在列表的头部或者尾部添加元素
命令
设置
在头部插入数据
LPUSH key value [value ...]
在尾部插入数据
RPUSH key value [value ...]
在一个元素的前|后插入新元素
LINSERT key BEFORE|AFTER pivot value
设置指定索引的元素值
索引是基于0的下标
索引可以是负数,表示偏移量是从list尾部开始计数,如-1表示列表的最后一个元素
LSET key index value
获取
移除并且返回 key 对应的 list 的第一个元素
LPOP key
移除并返回存于 key 的 list 的最后一个元素
RPOP key
返回存储在 key 的列表里指定范围内的元素
start 和 end 偏移量都是基于0的下标
偏移量也可以是负数,表示偏移量是从list尾部开始计数,如-1表示列表的最后一个元素
LRANGE key start stop
其它
裁剪列表,改为原集合的一个子集
start 和 end 偏移量都是基于0的下标
偏移量也可以是负数,表示偏移量是从list尾部开始计数,如-1表示列表的最后一个元素
LTRIM key start stop
返回存储在 key 里的list的长度
LLEN key
返回列表里索引对应的元素
LINDEX key index

3.3.5 set

无序集合
元素为string类型
元素具有唯一性,不重复
命令
设置
添加元素
SADD key member [member ...]
获取
返回key集合所有的元素
SMEMBERS key
返回集合元素个数
SCARD key
其它
求多个集合的交集
SINTER key [key ...]
求某集合与其它集合的差集
SDIFF key [key ...]
求多个集合的合集
SUNION key [key ...]
判断元素是否在集合中
SISMEMBER key member

2.3.6 zset

sorted set,有序集合
元素为string类型
元素具有唯一性,不重复
每个元素都会关联一个double类型的score,表示权重,通过权重将元素从小到大排序
元素的score可以相同
命令
设置
添加
ZADD key score member [score member ...]
获取
返回指定范围内的元素
ZRANGE key start stop
返回元素个数
ZCARD key
返回有序集key中,score值在min和max之间的成员
ZCOUNT key min max
返回有序集key中,成员member的score值
ZSCORE key member

3.4 与python交互

安装包
到中文官网查找客户端代码
联网安装
sudo pip install redis
使用源码安装
unzip redis-py-master.zip cd redis-py-master sudo python setup.py install
交互代码
引入模块
import redis
连接
try: r=redis.StrictRedis(host=‘localhost‘,port=6379) except Exception,e: print e.message
方式一:根据数据类型的不同,调用相应的方法,完成读写
更多方法同前面学的命令
r.set(‘name‘,‘hello‘) r.get(‘name‘)
方式二:pipline
缓冲多条命令,然后一次性执行,减少服务器-客户端之间TCP数据库包,从而提高效率
pipe = r.pipeline() pipe.set(‘name‘, ‘world‘) pipe.get(‘name‘) pipe.execute()

封装
连接redis服务器部分是一致的
这里将string类型的读写进行封装

import redis
class RedisHelper():
    def __init__(self,host='localhost',port=6379):
        self.__redis = redis.StrictRedis(host, port)
    def get(self,key):
        if self.__redis.exists(key):
            return self.__redis.get(key)
        else:
            return ""
    def set(self,key,value):
        self.__redis.set(key,value)