笔记迁移

This commit is contained in:
结发受长生 2018-05-12 19:51:10 +08:00
parent 5654d3f6db
commit a29cff3aed
41 changed files with 1377 additions and 0 deletions

View File

@ -0,0 +1,36 @@
---
title: 1.0、NoSQL
date: 2018-5-12 18:10:10
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
NoSQL ( Not Only SQL ) , 泛指`非关系型数据库`
传统的关系型数据库在超大规模和高并发的纯动态网站已经显得力不从心 , 暴露了很多难以克服的问题
NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战 , 尤其是大数据应用难题
<!-- more -->
> NoSQL数据库的共同特征
+ `不需要预定义模式`
不需要事先定义数据模式,预定义表结构。数据中的每条记录都可能有不同的属性和格式。当插入数据时,并不需要预先定义它们的模式。
+ `无共享架构`
相对于将所有数据存储的存储区域网络中的全共享架构。NoSQL往往将数据划分后存储在各个本地服务器上。因为从本地磁盘读取数据的性能往往好于通过网络传输读取数据的性能从而提高了系统的性能。
+ `弹性可扩展`
可以在系统运行的时候,动态增加或者删除结点。不需要停机维护,数据可以自动迁移。
+ `分区`
相对于将数据存放于同一个节点NoSQL数据库需要将数据进行分区将记录分散在多个节点上面。并且通常分区的同时还要做复制。这样既提高了并行性能又能保证没有单点失效的问题。
+ `异步复制`
和RAID存储系统不同的是NoSQL中的复制往往是基于日志的异步复制。这样数据就可以尽快地写入一个节点而不会被网络传输引起迟延。缺点是并不总是能保证一致性这样的方式在出现故障的时候可能会丢失少量的数据。
+ `BASE`
相对于事务严格的ACID特性NoSQL数据库保证的是BASE特性。BASE是最终一致性和软事务。
---
#### mongoDB的优点
1. `无数据结构的限制` , 没有表结构的概念 , 每条记录可以有完全不同的结构 . 业务开发方便快捷
而关系型数据库则必须要首先定义表结构 , 当数据结构发生变化通常需要修改表结构 , 添加字段等
2. `完全的索引支持` 键值索引 , 单键索引 , 多键索引 , 数组索引 , 全文索引 , 地理位置索引(2D)
3. `安全性与可扩展性` 复制集保证数据安全 , 分片扩展数据规模
4. `良好的支持` 完善的文档支持与驱动支持

View File

@ -0,0 +1,48 @@
---
title: 1.1、MongoDB的安装与配置
date: 2018-5-12 18:34:01
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
1. **安装mongoDB的安装包**
直接在官网下载即可
2. **创建数据库目录与日志目录**
<!-- more -->
例如在D盘创建目录
**D:/mongoDB/data/db**作为数据库存储目录
**D:/mongoDB/data/log**作为数据库日志的存储目录
3. **添加windows service**
在控制台执行以下命令
(1) 定位到自己的mongodb的安装目录\bin
例如 **cd C:\Program Files\mongodb\bin**
(2) 创建服务
```
mongod --dbpath "D:/mongoDB/data/db" --logpath "D:/mongoDB/data/log/mongdb.log" --install --serviceName "MongoDB"
```
其中包含的两个路径是在上一步中创建的数据库目录和日志目录(日志目录需要加上文件的名称)
4. **启动MongoDB服务**
![mongodb_server](/images/MongoDB/mongodb_server.png)
5. **尝试访问`http://localhost:27017/`**
如果可以正常访问 , 代表mongoDB的安装配置成功
6. **连接数据库**
直接执行安装目录下bin当中的mongo.exe文件
C:\Program Files\MongoDB\Server\3.2\bin\mongo.exe
在控制台访问数据库 , 执行help可以查看指令列表
7. **可视化工具**
可以试用robomongo作为可视化工具

View File

@ -0,0 +1,67 @@
---
title: 2.0、数据库基本操作
date: 2018-5-12 18:36:30
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
mongoDB当中也存在数据库和表的划分
但是这里的一个表可以看做是一个集合
里面可以容纳各种结构的数据x
每一条数据的结构可以各不相同
<!-- more -->
### 基本信息
+ `show dbs` 查看数据库列表
+ `show collections` 显示当前数据库当中的集合( 类似于关系型数据库中的表 )
+ `show users` 显示用户
+ `use 数据库名称` 切换数据库
+ `db.createCollection('集合名称')` 创建集合
mongoDB没有创建数据库的命令
可以直接使用use 数据库名称 切换数据库 , 然后创建任意一个集合 , 这个数据库就会自动创建
+ `db.dropDatabase()` 删除当前正在使用的数据库
+ `db.集合名称.drop()` 删除当前数据库的指定集合
### 插入数据
首先切换到需要使用的数据库 , 然后执行
```
db.<集合名称>.insert(数据)
```
这里的数据是json结构
执行插入数据过后
数据当中会自动生成一个主键_id属性 , 全局唯一
![insert](/images/MongoDB/insert.png)
这个属性值也可以在插入数据的时候指定
执行的命令当中也可以使用流程控制的语法
比如`for(i=0;i<20;i++)db.集合名称.insert({"x":i}) `
( 属性名也可以不加双引号 , 因为它一定是字符串 , 下同 )
修改数据
```
db.集合名称.update(筛选条件,新数据,[是否新增],[是否批量更新])
```
+ 筛选条件和新数据都是json形式的 , 是必填参数
+ 第三个参数是可选的 , 当筛选条件没有匹配到任何数据的时候 , 是否将新数据插入到集合当中 , 默认是false
如果省略第三个参数 , 或者传入false , 那么当筛选条件没有匹配到数据
该函数不会有任何效果
+ 第四个参数是可选的 , 表示当该筛选条件匹配到多条数据时 , 是否更新全部 , 默认为false ( 目的是为了防止批量覆盖数据的误操作 ) , 当该参数使用true的时候 , 必须使用$set操作符进行部分数据的更新操作 , 具体方式下面有介绍
例如
**db.demo.update( {x:1}, {x:99} )**
> 直接使用上述方式会覆盖整条数据的内容
如果要修改数据的部分内容
比如有如下数据 : { "x":10 , "y":10 , "z":10 }
可以使用$set操作符
例如 db.demo.update( {x:10}, {$set : {y:20} } )
这样只会修改y的值 , x和z的值都不变
### 数据删除
```
db.集合名称.remove(筛选条件)
```
为了防止误操作 , 筛选条件是必填的

View File

@ -0,0 +1,58 @@
---
title: 2.1、数据查询
date: 2018-5-12 18:42:37
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
#### `db.集合名称.find([查询条件],[查询的字段])`
+ 查询条件是JSON格式的数据
省略表示查询该集合当中的全部数据
+ 查询的字段也是用JSON格式表示 ,字段值是非零表示包含该字段 , 0则表示排除该字段 ( 但两种方式不能同时用 )
<!-- more -->
比如 {x : 1} 表示只查询主键_id和字段x的内容
主键\_id是默认被包含的 , 如果要排除可以写 { \_id : 0 }
> `db.集合名称.findOne()` 表示只返回查询结果的第一条数据
#### 模糊查询条件
直接使用普通的json是作为精确条件
也可以使用某个范围作为模糊条件
例如
`{age:{$gt:22}}`
是查找age字段大于22的数据
( 也可以应用于字符串 )
|操作符| 含义|
|---|----|
|$gt|大于|
|$lt|小于|
|$gte|大于等于|
|$lte|小于等于|
字符串的模糊匹配使用类似JavaScript当中正则表达式的方式
比如`/mongodb/`表示包含"mongodb"子串
相当于 `...where xx like '%mongodb%'`
`/^mongodb/`表示以"mongodb"开头
#### 逻辑运算符
+ **逻辑与 $and: **一个json中写的多个键值对本身就表示and
也可以用`{$and:[{a:1},{b:2}]}`表示`... where a=1 and b=2`
+ **逻辑或 $or: ** `{$or:[{a:1},{b:2}]}`
表示 `... where a=1 or b=2`
+ **某个字段 存在/不存在 $exists : **`{a:{$exists:true}}`表示存在a字段的数据
#### 对查询结果的处理
以下都是在`db.集合名称.find(查询条件)`获得的查询结果的基础上执行的函数
**结果计数**
`.count()`
对查询结果执行count函数 , 可以统计查询结果的数量
**分页查询**
`.skip(num).limit(num)`
skip表示跳过前面的若干条数据 , limit是返回数据的最大数量
**结果排序**
`.sort(排序条件)`
排序条件是json的形式 { 字段名 : 1 } 或者 { 字段名 : -1 }
前者表示升序 , 后者表示降序 , 不能用其他的数字

View File

@ -0,0 +1,71 @@
---
title: 3.0、索引
date: 2018-5-12 18:45:33
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
索引是对数据库表中一列或多列的值进行排序的一种结构,进行排序以后 , 数据的检索效率就会极大提高 , 因为不需要遍历所有的数据 , 所以使用索引可快速访问数据库表中的特定信息。
<!-- more -->
#### 查看集合当中的索引
```
db.集合名称.getIndexes()
```
每个集合当中都包含一个默认创建的索引 , 就是主键id的索引 , 名称是 \_id\_
![getIndexes](/images/MongoDB/getIndexes.png)
#### mongoDB当中的索引类型
+ `_id索引` : 在集合被创建的时候自动添加的索引 , 不能删除 ( 也是一种单键索引 )
+ `单键索引` : 针对单个字段创建的索引
+ `多键索引` : 在数组元素上建立的索引 , 会对数组的每个元素添加索引
+ `复合索引` : 针对多个字段创建的索引
+ `过期索引` : 在一定时间后会过期的索引 , 索引过期后 , 相应的数据会被删除
适合存储一些登陆信息 日志等数据
+ `全文索引`
+ `地理位置索引`
#### 创建索引
```
db.集合名称.ensureIndex( {索引字段名1: 1 , 索引字段名2 : 1 ...} , [索引属性] )
```
索引类型1表示按照升序方式存储索引 , -1表示降序
有多个索引字段时 , 该索引就是一个复合索引
索引属性的可选参数 , 后面有具体的介绍
##### 创建过期索引
```
db.集合名称.ensureIndex( {索引字段名 :1 ...} , {expireAfterSeconds : 过期的秒数} )
```
注意 :
1. 过期索引对应的字段必须是Date类型 或者 Date的数组 , 否则不会被自动删除
-> 可以使用 .insert( {time : new Date()} ) 来获取当前的日期时间
2. 如果是Date的数组 , 只要有其中任意一个到了过期时间 , 该数据就会被删除
3. 过期索引不可以是复合索引
4. 删除的执行是由后台的一个60s执行一次的定时任务完成 , 所以删除的时间是不精确的
#### 删除索引
```
db.集合名称.dropIndex("索引名称")
```
注意是索引名称 , 而不是索引所对应的字段
---
#### 补充
**在执行查询时强制使用索引**
```
db.集合名称.find( 查询条件 ).hint( 索引名称 )
```
**索引当中的其他几个重要的属性**
+ `name` - 索引的名称 , 不指定的话可以由系统自动生成
+ `unique` - (true/false) 索引的唯一性 , 相当于为添加该索引的某个或多个字段添加了唯一约束 , 不能插入重复的两条数据 (默认false)
+ `sparse` - (true/false) 稀疏性 默认false , 为某个字段添加索引之后 , 由于非关系型数据库的特点 , 某条数据可能并不包含该字段的键值对数据 , 如果在非稀疏的模式下 , 也会为该数据创建索引 , 如果不希望如此 , 可以把sparse置为true . 有助于减少磁盘占用 , 提高写入性能
注意 : 鉴于稀疏索引本身的这种特性 , 如果我们强制使用稀疏索引去查找不存在某个字段的数据 , 就会出现问题 , 因为这些数据不存在于稀疏索引当中
例如 "m_1"是一个针对m字段的稀疏索引
执行 db.test.find({m : {$exists:false }}).hint("m_1")
即使有符合条件的数据 , 也不可能返回任何结果

View File

@ -0,0 +1,63 @@
---
title: 3.1、全文索引
date: 2018-5-12 18:53:10
tags:
- 数据库
- MongoDB
- 索引
categories:
- MongoDB
---
`全文索引`是目前搜索引擎的关键技术
对于在大量的大文本当中搜索一个关键词
如果没有全文索引 , 只能是使用正则匹配进行遍历
效率十分低下
<!-- more -->
所以在这样的矛盾之下出现了全文索引技术 , 也称为`倒排文档技术`
无论是对于庞大的互联网数据的爬取还是应用的站内搜索功能 , 全文索引都是能极大提高性能的一种技术
在mongoDB当中 , 全文索引是对字符串或字符串数组来创建全文索引
#### 创建全文索引
```
db.集合名称.ensureIndex({key_1:"text"...)
```
与普通的单键索引或者符合索引有区别的是
json当中的值是一个 **固定字符串”text”** , 而不是整数
上述写法是对某个或者某几个字段创建全文索引
但是取决于mongoDB存储数据的特点
每个集合当中的数据可以有完全不同的结构
所以通常用如下得到方式对该集合当中所有的字符串或字符串数组字段添加全文索引
```
db.集合名称.ensureIndex({"$**":"text"})
```
> 每个集合当中只能创建一个全文索引
#### 使用全文索引进行查询
+ `find({$text:{$search:"aa"}})` - 普通单关键字匹配
+ `find({$text:{$search:"aa bb"}})` - 多关键字匹配 ( 不同关键字之间是或的逻辑关系 )
+ `find({$text:{$search:"\"aa\" \"bb\""}})` - 多关键字匹配 ( 不同关键字之间是与的逻辑关系 )
+ `find({$text:{$search:"aa bb -cc"}})` - 添加屏蔽的关键字
> **注意** : 上述的全文索引的搜索方式是根据英文单词进行匹配的 , 也就是按照空白( 包括空格 换行 制表符等 )分割的字符串 , 如果关键词是单词的一部分 , 或者是中文内容 , 这种方式就无法检索到需要的数据
#### 相似度查询
`$meta`操作符 { score : {$meta : “textScore”} }
( 注意textScore是固定的操作符标识 , 代表相似度值 )
写在查询条件后面可以返回结果的相似度
例如 在一个添加了全文索引的集合当中有下列数据
![full text search](/images/MongoDB/full_text_search1.png)
执行下面的查询
```
db.集合名称.find({$text:{$search:"aa"}},{score:{$meta:"textScore"}})
```
结果如下
![full text search](/images/MongoDB/full_text_search2.png)
> 目前新版的mongoDB执行全文索引的查询后的结果默认就是按照相似度降序排列的
添加全文索引会导致集合的写入性能下降 , 因为所有的字符串都要拆分 , 存储到不同的地方

View File

@ -0,0 +1,49 @@
---
title: 3.2.1、GeoJSON
date: 2018-5-12 19:14:34
tags:
- 数据库
- MongoDB
- 索引
categories:
- MongoDB
---
GeoJSON是一种对各种地理数据结构进行编码的格式。GeoJSON对象可以表示几何、特征或者特征集合。GeoJSON支持下面几何类型点、线、面、多点、多线、多面和几何集合。GeoJSON里的特征包含一个几何对象和其他属性特征集合表示一系列特征。
<!-- more -->
特点
+ GeoJSON对象可能有任何数目成员名/值对)。
+ GeoJSON对象必须由一个名字为`type`的成员。这个成员的值是由GeoJSON对象的类型所确定的字符串。
+ type成员的值必须是下面之一**"Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", "GeometryCollection", "Feature", 或者 "FeatureCollection"**。这儿type成员值必须如这儿所示。
+ GeoJSON对象可能有一个可选的"crs"成员,它的值必须是一个坐标参考系统的对象。
+ GeoJSON对象可能有一个"bbox"成员,它的值必须是边界框数组
> `几何`是一种GeoJSON对象( 相当于是一个子集 )这时type成员的值是下面字符串之一**"Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", 或者"GeometryCollection"**。
> 除了“GeometryCollection”外的其他任何类型的GeoJSON几何对象必须包含一个名字为`coordinates`的成员。coordinates成员的值总是数组。这个数组里的元素的结构由几何类型来确定。
`位置`是基本的几何结构。几何对象的"coordinates"成员由一个位置(这儿是几何点)、位置数组(线或者几何多点),位置数组的数组(面、多线)或者位置的多维数组(多面)组成。
#### 几何的类型
+ 点 ( Point )
“coordinates"成员必须是一个单独的位置。
+ 多点 ( MultiPoint )
"coordinates"成员必须是位置数组。
+ 线 ( LineString )
“coordinates"成员必须是两个或者多个位置的数组。
+ 多线 ( MultiLineString )
"coordinates"成员必须是一个线坐标数组的数组。
+ 面 ( Polygon )
"coordinates"成员必须是一个线性环坐标数组的数组。对拥有多个环的的面来说,第一个环必须是外部环,其他的必须是内部环或者孔。
+ 多面 ( MultiPlygon )
"coordinates"成员必须是面坐标数组的数组。
+ 几何集合 ( GeometryCollection )
它表示几何对象的集合。
几何集合必须有一个名字为`geometries`的成员。与"geometries"相对应的值是一个数组。这个数组中的每个元素都是一个GeoJSON几何对象。

View File

@ -0,0 +1,89 @@
---
title: 3.2、地理位置索引
date: 2018-5-12 19:11:32
tags:
- 数据库
- MongoDB
- 索引
categories:
- MongoDB
---
概念 : 将一些点的位置存储在MongoDB当中
创建索引后 , 可以按照位置来查找其他点
<!-- more -->
子分类
1. 2D索引 , 用于存储和查找平面上的点
2. 2Dsphere索引 , 用于存储和查找球面上的点
查找方式
1. 查找距离某个点一定距离内的点
2. 查找包含在某区域内的点
#### 2D索引
位置使用经纬度两个值构成的数组来表示
取值范围 : 经度 [-180 , 180] , 纬度 [-90 , 90]
##### 添加2d索引
```
db.集合名称.ensureIndex( { 字段名 : "2d" } )
```
添加该索引之后 , 向该集合当中插入的数据 , 如果该字段不符合经纬度的要求 , 就会报错
##### 查询方式
`$near` 查询距离某个点距离最近的点 , 并且从近到远排列 , 默认至多返回100条数据
如果一个集合当中已有了如下的数据 , 并且已添加2d索引
![location index](/images/MongoDB/location_index1.png)
执行查询
`.find({w:{$near:[50,50]}}) `
获得的结果如下
![location index](/images/MongoDB/location_index2.png)
如果要查询检索的范围
可以用$maxDistance 和 $minDistance操作符
表示最远距离和最近距离 , 不在这个范围内的点将会被过滤掉
![location index](/images/MongoDB/location_index3.png)
> 也可以使用`db.runCommand`方法 , 这个方法可以有更加详细的参数和返回结果
比如 **db.runCommand({getNear:”test”,near:[5,5],manDistance:20,num:3}**
返回的结果可以获得符合要求的点与指定点的距离 , 以及平均距离等数据
##### `$geoWithin`查询某个形状内的点
1. `$box:[ [x1, y1] , [x2 , y2] ]` 表示矩形 , 参数分别表示左下坐标和右上坐标
2. `$center :[[x1,y1] , r]` 表示圆形 , 参数是圆心和半径
3. `$polygon : [[x1,y1],[x2,y2] ...]` 表示多边形 , 参数为多边形每个顶点的坐标
例如 **.find({w:{$geoWithin:{$box:[[1,1],[50,50]]}}})**
其他两种方式用法同理
#### 2Dsphere索引
球面地理位置索引
创建方式
```
db.集合名称.ensureIndex({w:"2dsphere"})
```
但是在这个索引对应的字段当中
数据就要使用GeoJSON来表示
格式如下
```
{type:"",coordinates:[<coorinates>]}
```
> 关于GeoJSON的详细规范 , 参考下一篇笔记
##### 查询
举例 : 查询一个多边形当中的所有位置
```json
{ w:
{ $geoWithin :
{ $geometry :
{
type : "Polygon" ,
coordinates : [[[0,0],[3,6],[6,1],[0,0]]]
}
}
}
}
```
+ `$geoIntersects`区域交叉 , 查询与多边形相交的所有的点和形状
+ `$near`临近 , 与2D索引类似

View File

@ -0,0 +1,87 @@
---
title: 3.3、索引构建情况分析
date: 2018-5-12 19:16:06
tags:
- 数据库
- MongoDB
- 索引
categories:
- MongoDB
---
索引本身可以提高查询的效率
但是数据库要维护索引 , 需要额外的磁盘空间占用 , 并且写入的性能也会下降
<!-- more -->
要评判数据库当中的索引构建情况
常用的有下列4种方式
1. mongostat工具
2. profile集合
3. mongoDB自身的日志
4. explain分析
#### mongostat
这是mongoDB自带的一个工具 , 可以查看mongoDB的运行状态
> 在mongoDB的安装目录\bin当中 , 有一个名为mongostat.exe的程序 , 将bin路径加入到环境变量之后 , 就可以直接在控制台运行该程序
使用方式
`mongostat -h <IP地址>:<端口号>`
例如
mongostat -h 127.0.0.1:27017
这是一个针对mongoDB的综合监控程序
每秒根据各项指标进行采样
其中常用的各项指标的含义 ( 均是以每秒为单位 )
+ inserts - 写入数据的次数
+ query - 查询数据的次数
+ update - 更新数据的次数
+ delete - 删除数据的次数
+ getmore - 当查询的数据量较大时 , 为了防止内存溢出 , 并不会一次返回所有的数据 , 而是分批返回 , 获取下一批的数据执行的是getmore
+ command - 执行命令的数量
+ flushed - 将内存中的数据写入到硬盘的次数
+ vsize - 虚拟内存使用量单位MB
+ res - 物理内存使用量单位MB
+ faults/s - 访问失败数只有Linux有数据被交换出物理内存放到swap。不要超过100否则就是机器内存太小造成频繁swap写入。此时要升级内存或者扩展
+ ids miss - 查询没有命中索引的比例 ( 如果太高的话可能是创建了不合理的索引或者索引的数量不够 , 是一个潜在隐患 , 数据量过大就可能出现性能问题 )
+ qr | qw - 读队列/写队列 , 如果值较高的话就代表读写的负载比较高 , 可能出现性能问题
+ ar | aw - 当前活跃的客户端的数量
+ conn - 连接数量
#### profile集合
在mongoDB当中存在一个记录读写操作日志的集合
使用`db.getProfilingLevel()`可以获得当前的记录级别
+ 0 关闭 , 不做任何记录
+ 1 开启 , 有慢查询的时候记录
+ 2 开启 , 记录所有内容
默认是0 , 可以使用`db.setProfilingLevel(1)`开启慢查询的记录
从而通过分析这个集合当中的数据
有针对性的通过创建所以解决慢查询的问题
也可以在配置文件中配置`profile=1`来进行默认开启
`slowms`参数表示慢查询的毫秒数 , 查询所用的时间超过这个值的就是慢查询 , 默认是100
> 由于向profile当中写入数据本身也是占用性能的 , 尤其是这个集合当中内容较多的情况下
> 所以这种方式的应用场景通常是在开发和测试阶段
#### mongoDB的日志
在1.1的mongoDB安装配置步骤当中 , 第三步是创建windows服务以方便使用
并且配置了数据库所在路径和日志所在路径
这个服务实际是执行了mongod命令来启动数据库
并且传递了dbpath和logpath两个参数用来指定数据的存储位置和日志的写入路径
我们也可以在本地创建一个配置文件( 通常是conf格式 )来配置这些参数 , 从而方便进行配置的修改
`mongod --config "配置文件路径" --install --serviceName "MongoDB"`
配置文件内容的写法与.properties文件相同
其中常用的配置项有
+ dbpath - 数据目录
+ port - 服务器监听的端口 , 默认是27017
+ fork - (true/false) 是否以守护进程方式运行
+ logpath - 日志输出路径
+ verbose - (v~vvvvv) 日志信息冗余级别 , v越多详细度越高
+ bind_ip - 绑定的IP地址 , 绑定以后只能通过该IP与数据库连接 ( 多个IP用逗号分隔 )
+ maxConns - 最大连接数
#### explain分析
用法 : **在find函数的返回结果上调用explain()**
这个函数会返回这次查询的相关信息用于分析

View File

@ -0,0 +1,73 @@
---
title: 4.0、安全验证
date: 2018-5-12 19:24:14
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
mongoDB在默认情况下是没有开启权限认证的 , 也就是不需要用户名密码就可以连接数据库
<!-- more -->
#### 创建用户
```
db.createUser(<userinfo>)
```
其中userinfo是一个json数据 , 包含下列属性
+ user - 用户名
+ pwd - 密码
+ customData - 任意的自定义内容
+ roles : [{ role : <角色类型>, db : <数据库名称> } , … ]
一个用户可以对应多个角色 , 所以是一个数组结构
mongoDB当中内置的角色类型有
+ 数据库用户角色read、readWrite;
允许用户 读/读写 指定的数据库
+ 数据库管理角色dbAdmin、dbOwner
允许在指定数据库中执行管理函数 , 如索引增删 查看统计等
+ 用户管理角色userAdmin
允许向system.users集合写入数据, 可以在指定数据库增删用户
+ 集群管理角色clusterAdmin、clusterManager、clusterMonitor、hostManager
+ 备份恢复角色backup、restore
+ 所有数据库角色readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
可以在所有数据库中进行 读/读写/用户管理
+ 超级用户角色root
+ 内部角色__system
举例
```javascript
db.createUser({
user:"sookie",
pwd:"123456",
customData:{info:"this is my first user"},
roles:[
{role:"userAdmin",db:"admin"},
{role:"read",db:"demo"}
]
})
```
#### 开启权限认证
在配置文件中添加 ( 关于配置见前一节的内容 )
`auth=true `
重启服务即可开启数据库的权限认证
#### 认证用户
连接到mongoDB数据库以后 , 由于开启了权限认证
如果不进行用户认证 , 是没有任何权限的
![auth](/images/MongoDB/auth.png)
进行认证的步骤如下
切换到用户所在的数据库 , 比如刚才创建的用户在demo数据库下具有”read”权限
就执行`use demo`
执行`db.auth("用户名","密码")`
> **注意** 帐号是跟着库走的,所以在指定库里授权,必须也在指定库里验证(auth)
认证完成后 , 当前用户就可以执行权限所允许的操作了
---
附 : 在Robomongo当中使用指定用户访问数据库的方法
![auth](/images/MongoDB/auth_robomongo.png)

View File

@ -0,0 +1,80 @@
---
title: 5.0、Java操作MongoDB数据库
date: 2018-5-12 19:26:45
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
所需要的[驱动jar包](http://mvnrepository.com/artifact/org.mongodb/mongo-java-driver)
<!-- more -->
#### (一) 连接MongoDB
一个`MongoClient`的实例代表一个客户端连接
从中可以获取到需要使用的数据库`MongoDatabase`对象
```java
MongoClient client = new MongoClient("localhost",27017);
MongoDatabase db = client.getDatabase("demo");
// 使用完毕后, 需要关闭客户端连接
client.close();
```
MongoClient是**线程安全**的可以在多程程环境中共享同一个MongoClient。通常来说一个应用程序中只需要生成一个全局的MongoClient实例
#### (二) 认证
上述方式是在数据库没有添加用户认证的情况下实现的连接
认证信息用`MongoCredential`对象表示
```java
ServerAddress address = new ServerAddress("localhost", 27017);
// 参数分别是 用户名 所在数据库 密码(char数组形式)
MongoCredential credential = MongoCredential.createCredential("sookie", "demo", "123456".toCharArray());
// 由于构造函数接受一个List对象, 所以需要进行一次包装
MongoClient client = new MongoClient(address, Arrays.asList(credential));
client.close();
```
#### (三) 获取一个集合
```java
MongoDatabase db = client.getDatabase("demo");
//获取指定名称的集合
MongoCollection<Document> collection = db.getCollection("test");
```
在集合对象上就可以直接进行增删改查的操作
#### (四) 数据对象
或者也可以称为文档 , 本身是一个JSON
使用`Document`对象来表示
任何需要JSON的地方都通用这个对象( 包括数据的查询结果 )
#### (五) 插入与删除
Document中的静态方法parse可以将JSON字符串转化为Document对象 , 用于插入方法的参数
```java
Person person = new Person("Sookie",18);
Document doc = Document.parse(JSON.toJSONString(person));
collection.insertOne(doc);
```
insert相关的方法也可以接受Map对象等作为参数 , 具体的参考源码
删除使用`deleteOne``deleteMany`方法
前者表示删除符合条件的一条数据 , 后者表示删除符合条件的多条数据
```java
Bson filter = new BasicDBObject("age",18);
collection.deleteMany(filter);
```
> `Bson`是一个接口 , `BasicDBObject`是这个接口的一个实现类 , 可以作为查询条件
#### (六) 查询
```java
// 执行查询操作, 方法名称与终端所用的指令类似
FindIterable<Document> result = collection.find();
for (Document doc : result) {
System.out.println(doc);
}
```
find函数也有Bson作为参数的重载形式 , 查询条件的创建方式同上面的删除操作
包含$操作符的查询条件同样可以使用BasicDBObject创建

View File

@ -0,0 +1,124 @@
---
title: 5.1、morphia
date: 2018-5-12 19:32:23
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
`Morphia` 是一个轻量级的类型安全的 Java 类库,用来将在 MongoDB 和 Java 对象之间进行映射
对MongoDB的API进行了一些封装 , 类似hibernate
<!-- more -->
[maven仓库jar包](http://mvnrepository.com/artifact/org.mongodb.morphia/morphia)
---
由于使用MongoDB的原生jar包无法对实体类执行映射操作
如果有一个实体类的对象 , 比如要手工转化为Document对象才可以保存到数据库
同样 , 查询获得的结果也是Document对象 , 而不是实体类对象 , 使用相对不便
1. **创建实体类 , 并添加注解**
```java
@Entity(value="t_person")
public class Person {
@Id
private long id;
private String name;
private String address;
private int age;
//getter与setter方法...
}
```
可以在@Entry注解的value属性指定该实体类对应的集合名称
如果不指定 , 就默认为这个类的名称
2. **使用junit进行单元测试**
首先编写测试类的基类 , 需要进行连接的初始化和执行完毕后的连接关闭
```java
public class UnitTestBase {
protected Mongo mongo;
protected Morphia morphia;
protected Datastore ds;
private static final String HOST = "127.0.0.1";
private static final int PORT = 27017;
private static final String DB_NAME = "demo";
@Before
public void init() {
mongo = new MongoClient(HOST, PORT);
morphia = new Morphia();
ds = morphia.createDatastore(mongo, DB_NAME);
}
@After
public void desotry() {
mongo.close();
}
}
```
如果需要用户认证 , 直接对MongoClientt对象执行操作即可
方式参考前一篇笔记
3. **增删改查操作**
通常的增删改查方法如下
```java
public class MongodbTest extends UnitTestBase {
@Test
public void testSave(){
Person person = new Person(1002, "Molly", "excuse me?", 20);
ds.save(person);
// 注意:在执行save操作的时候, 如果对应的集合不存在, 则自动创建该集合
}
@Test
public void testDelete() {
Person person = new Person();
person.setId(1002);
//删除操作是根据主键来删除, 实体类中已经用@Id设定了主键
ds.delete(person);
}
@Test
public void testUpdate() {
Person person = new Person();
person.setId(1002);
UpdateOperations<Person> ops = ds.createUpdateOperations(Person.class);
ops.set("name", "Polly");
ops.set("address", "000");
//第一个参数是过滤条件, 第二个参数是需要修改的属性和值的集合
ds.update(person, ops);
/*
* update方法是修改所有符合条件的数据
* 如果只需要修改符合条件的第一条数据, 可以使用
* ds.updateFirst(query, ops)
*/
}
@Test
public void testQuery(){
Query<Person> result = ds.find(Person.class, "name", "Molly");
//第二个与第三个参数是查询的条件
for(Person per : result) {
System.out.println(per);
}
/*
* 在查询当中, 如果集合中的文档有额外的字段, 会被忽略
* 实体类中有而文档中没有的字段
* 查询结果的对象中对应属性就是null或者基本数据类型的默认值
*/
}
}
```
以上的增删改查方法都有多种重载形式 , 在这里就不一一举例了
具体的可以查看morphia源代码
---
上述方式是使用注解添加类的映射
如果不用注解 , 也可以手动把某些类加载到morphia当中
```java
//将若干个类加入到映射
morphia.map(Person.class);
//将某个包中的所有类添加到映射
morphia.mapPackage("com.entry");
```

View File

@ -0,0 +1,130 @@
---
title: 5.2、关联映射
date: 2018-5-12 19:37:03
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
在Maven项目中引入marphia的包
```xml
<dependency>
<groupId>org.mongodb.morphia</groupId>
<artifactId>morphia</artifactId>
<version>1.2.0</version>
</dependency>
```
<!-- more -->
![mapping](/images/MongoDB/mapping1.png)
maven会自动引入一些其他的依赖jar包 , 否则关联映射就无法正常执行
---
#### 命令行执行
```javascript
db.user.insert({
username:"test_user",
role : {
$ref:"role",
$id:ObjectId("576d47b8cc7a1342538343fc"),
$db:"model_db"
}
})
```
> **说明** : 在NoSQL型数据库当中 , 并不鼓励使用类似于关系型数据库的外键关联
> 但是为了程序的查询方便 , 提供了这种程序驱动可以识别的表示形式
> 其实并没有外键关联的检查 , 与普通的文档没有任何区别
#### 使用morphia的注解实现引用
##### 多对一关联
`@Reference`注解包含的属性
+ concreteClass - 关联的目标类
+ idOnly - 只保存从表的数据ID ( 与关系型数据库的外键字段类似 )
+ ignoreMissing - 忽略不能解决的引用
+ lazy - 懒加载 , 默认是false ( 在双向关联情况下 , 如果双端都不是懒加载 , 会形成死循环 )
+ value - 在集合中存储的字段名 , 默认是类中的属性名
角色表
```java
@Entity(value="role")
public class Role {
@Id
private ObjectId id;
private String roleName;
private String remark;
//getter与setter方法
}
```
用户表
```java
@Entity(value="user")
public class User {
@Id
private ObjectId id;
private String username;
private int age;
private boolean denger;
@Reference(value="roleId",idOnly=true)
private Role role;
//getter与setter方法
}
```
测试代码
```java
User user = new User();
user.setUsername("papapa");
Role role = new Role();
role.setRoleName("测试角色2");
user.setRole(role);
ds.save(role);//ds -> Datastore
ds.save(user);
```
![mapping](/images/MongoDB/mapping2.png)
##### 一对多关联
用法与多对一也是类似的 , 数据库中会在 **一** 的那端以数组形式保存数据
```java
@Entity(value="role")
public class Role {
@Id
private ObjectId id;
private String roleName;
private String remark;
@Reference("user")
private List<User> users;
//getter与setter方法
}
```
测试代码
```java
@Test
public void save(){
Role role = new Role();
role.setRoleName("测试角色2");
User user1 = new User();
user1.setUsername("pppp");
User user2 = new User();
user2.setUsername("oooo");
List<User> users = new ArrayList<User>();
users.add(user1);
users.add(user2);
userDao.save(user1);
userDao.save(user2);
role.setUsers(users);
roleDao.save(role);
}
```
![mapping](/images/MongoDB/mapping3.png)

View File

@ -0,0 +1,38 @@
---
title: 6.0、复制集
date: 2018-5-12 19:45:02
tags:
- 数据库
- MongoDB
- 集群
categories:
- MongoDB
---
复制集是由一组拥有相同数据集的mongod实例所组成的`集群`
<!-- more -->
在这个复制集集群当中 , 各个节点可能有以下几种状态
+ `Primary` 主节点一个复制集至多有一个节点处于Primary状态只有主节点才对外提供读写服务。如果主节点挂掉复制集将会投票选出一个备用节点成为新的主节点。
+ `Secondary` 备用节点,复制集允许有多个备用节点,每个备用节点的数据与主节点的数据是完全同步的。
+ `Recovering` 恢复中,当复制集中某台服务器挂掉或者掉线后数据无法同步,重新恢复服务后从其他成员复制数据,这时就处于恢复过程,数据同步后,该节点又回到备用状态。
+ `Arbiter` 仲裁节点,该类节点可以不用单独存在,如果配置为仲裁节点,就主要负责在复本集中监控其他节点状态,投票选出主节点。该节点将不会用于存放数据。如果没有仲裁节点,那么投票工作将由所有节点共同进行。
+ `Down` 无效节点,当服务器挂掉或掉线时就会处于该状态。
复制集就是通过在备用节点上备份数据来提高数据库的可靠性
主节点会把所有的**写操作**记录到`oplog`当中
( 包括所有的增删改操作 )
备用节点通过oplog来进行数据的同步
> 对于mysql的集群部署 , 拥有super权限的用户可以在备用节点执行写入操作 , mongoDB的备用节点是绝对不可以进行写操作的
> 而且mysql的集群可以拥有双主结构
对于**读操作** , 默认情况下都是指向主节点的 , 虽然备用节点也在实时更新数据 , 但数据相对主节点来说也是有可能滞后的
如果对数据的时效性要求不是特别严格 , 也可以把读操作指向备用节点 , 从而分担主节点的压力
MongoDB复制集的特点
+ **数据一致性** - 主节点在一个集群中至多有一个 , 但并不是固定的 , 但可以设定节点的优先级 , 让一个性能更好的节点优先成为主节点
+ **大多数原则 ( 二分之一原则 )** - 集群存活节点小于等于二分之一的时候 , 集群不可写 , 只可读
也就是说 , 能否选举出新的主节点 , 是由当前复制集成员的存活数量来决定的
即使之前的主节点正常工作 , 备用节点挂掉的过多 , 这个主节点也会自动降级为备用节点
+ **备用节点无法写入** - 在备用节点写入数据有造成主键冲突的可能性
+ **自动容灾** - 主节点挂掉以后 , 会自动从备用节点中选举出一个主节点

View File

@ -0,0 +1,50 @@
---
title: 6.1、快速搭建复制集
date: 2018-5-12 19:47:03
tags:
- 数据库
- MongoDB
- 集群
categories:
- MongoDB
---
在一个复制集当中 , 每个节点都需要具备独立的进程 , 所以要分别进行配置
这里需要用到几个重要的配置项
<!-- more -->
+ `replSet` - 复制集的名称 , 不同节点设置的复制集名称必须一致 , 才能保证这些节点被加入到同一个复制集当中
+ `oplogSize` - 复制集的缓存大小 , 单位MB
( 不同的节点之间是通过oplog进行同步的 )
当然 , 如果要在一台机器上模拟一个复制集 , 对于每个节点的实例需要配置不同的端口号
步骤
1. 编写配置文件 , 并启动多个实例
2. 连接其中一个节点 , 执行配置
```javascript
config = {
_id:"TestReplSet",//复制集的唯一标识
members:[
//复制集当中的成员
{_id:0,host:"127.0.0.1:28001"},
{_id:1,host:"127.0.0.1:28002"},
{_id:2,host:"127.0.0.1:28003",
arbiterOnly:true
//置为仲裁节点
}
]
}
```
这里是相当于定义了一个名为config的全局变量
**其他的节点配置项**
> + `priority` - 值为整数 ( 0~1000 ) , 默认是1 , 代表这个节点的权重 , 也就是成为主节点的机会 , 如果是0则永远不会成为主节点
> + `hidden` - 是否是隐藏节点 , true/false , 如果设置为true , 那么priority必须是0
> + `vote` - 整数值 , 该节点是否具有投票权 , 值为0或1
> + `slaveDelay` - 整数值 , 延迟时间复制数据 , 单位是秒 ( 对于一些误操作 , 可以利用延时挽回数据的损失 )
3. 执行复制集的初始化
```javascript
rs.initiate(config)
```
稍等片刻即可完成复制集的搭建了

View File

@ -0,0 +1,43 @@
---
title: 7.0、使用浏览器访问MongoDB
date: 2018-5-12 20:42:18
tags:
- 数据库
- MongoDB
categories:
- MongoDB
---
MongoDB可以开启一个HTTP协议的端口提供REST服务 , 这个端口是数据库的服务端口加1000
比如数据库的服务端口是27017
那么开启REST服务之后 , 通过浏览器访问的端口就是28017
<!-- more -->
配置方式
+ `httpinterface` - 置为true表示开启HTTP协议端口
+ `rest` - 置为true表示开启rest服务
REST是mongoDB自带的一套API , 可以提供查询 , 但是不支持增删改操作 , 也不支持权限认证
配置完成之后重启服务 , 即可直接使用浏览器访问
![browser](/images/MongoDB/browser.png)
在主页面可以查看到数据库的一些基本情况
---
#### 执行查询操作
列出databaseName数据库中的collectionName集合下的所有数据
`http://127.0.0.1:28017/databaseName/collectionName/`
给上面的数据集添加一个limit参数限制返回10条
`http://127.0.0.1:28017/databaseName/collectionName/?limit=-10`
给上面的数据加上一个skip参数设定跳过5条记录
`http://127.0.0.1:28017/databaseName/collectionName/?skip=5`
同时加上limit限制和skip限制
`http://127.0.0.1:28017/databaseName/collectionName/?skip=5&limit=10`
按条件{a:1}进行结果筛选在关键字filter后面接上你的字段名
`http://127.0.0.1:28017/databaseName/collectionName/?filter_a=1`
加条件的同时再加上limit限制返回条数
`http://127.0.0.1:28017/databaseName/collectionName/?filter_a=1&limit=-10`
执行任意命令
如果要执行特定的命令可以通过在admin.$cmd上面执行find命令同样的你也可以在REST API里实现如下执行{listDatabase:1}命令:
`http://localhost:28017/admin/$cmd/?filter_listDatabases=1&limit=1`
查询集合的记录个数:`http://host:port/db/$cmd/?filter_count=collection&limit=1`

View File

@ -0,0 +1,104 @@
---
title: CSS动画(1)-transform
date: 2018-5-12 18:10:10
tags:
- 前端
- css
categories:
- 前端杂烩
---
CSS3当中与动画有关的属性有 :
+ transform - 变形
+ transition - 转换
+ animation - 动画
<!-- more -->
> **准备知识 :**
网页中对于元素所定义的坐标系
通常所关注的网页是一个平面
所以有X轴和Y轴
X轴是水平的 , 向右为正方向
Y轴是竖直的 , 向下为正方向
但是在元素动画相关的属性当中 , 存在3D变换
所以还需要一个Z轴
这个Z轴是垂直于平面 , 向外为正方向
![3d_axes](/images/前端杂烩/animation/3d_axes.png)
z-index属性值大小影响元素在Z轴方向上的排布与此同理
### transform
> 该属性只对block级元素生效
语法格式
<pre>
transform: &lt;transform-function&gt; [&lt;transform-function&gt;]* | none
</pre>
也就是说这个属性对应的值可以是none , 代表不进行任何变形
也可以使用一个或多个**变形函数**
多个函数之间是以**空格**进行分割
函数有以下几类 ( 每一类都有若干个分功能的函数 , 类似于margin与margin-top的关系 )
+ translate - 转换
+ rotate - 旋转
+ scale - 缩放
+ skew - 倾斜
#### rotate - 旋转
直接使用同名的函数表示2D旋转
参数是旋转的角度
```css
.rotate_div {
transform : rotate(30deg);
}
```
![rotate](/images/前端杂烩/animation/rotate.png)
deg是旋转的角度 , 正数表示顺时针旋转 , 负数表示逆时针旋转
也可以使用`trun`作为单位 , 表示一周 , 比如0.25turn实际就是90度
+ rotateX - 绕X轴旋转 ( 视觉效果上会在竖直方向上压缩 )
+ rotateY - 绕Y轴旋转 ( 视觉效果上会在水平方向上压缩 )
+ rotateZ - 绕Z轴旋转 , 实际上rotate本身执行的就是绕Z轴旋转
#### translate - 移动
同名函数接受2个参数 , 分别表示在X轴和Y轴上的移动距离 , 正数代表向该轴的正方向移动 , 负数代表向负方向移动
```css
.translate_div {
tranform : translate(100px, 20px);
}
```
![translate-x-y](/images/前端杂烩/animation/translate-x-y.png)
+ translateX - 在X轴方向移动
+ translateY - 在Y轴方向移动
+ translateZ - 在Z轴方向移动
( 父元素需要有perspective属性的设置才能生效 这个属性代表透视点在Z轴上的位置 )
#### scale - 缩放
同名函数接受两个参数 , 分别表示在X轴和Y轴上的缩放比例 , 大于1是放大 , 小于1是缩小
```css
.scale_div {
transform : scale(2, 1.5);
}
```
![scale-x-y](/images/前端杂烩/animation/scale-x-y.png)
+ scaleX - 在X轴方向缩放
+ scaleY - 在Y轴方向缩放
+ scaleZ - 在Z轴方向缩放 ( 当然需要其他的效果 , 比如绕X轴旋转 , 使元素在Z轴方向上有一定的纵深 , 才会有效果 )
+ scale3d - 包含3个参数 , 分别是在XYZ轴上的缩放比例
#### skew - 倾斜
同名函数可以提供1或者2个参数 , 如果只提供1个参数 , 代表在X轴方向的倾斜角度
如果提供两个参数 , 分别代表在X轴和Y轴方向的倾斜角度
```css
.skew_div {
transform : skew(30deg, 10deg);
}
```
![skew-x-y](/images/前端杂烩/animation/skew-x-y.png)
同样有 skewX 与 skewY , 与上面的几个函数类似 , 不过没有Z轴方向的
> 旋转与倾斜 , 都与元素的基点有关系 , 默认情况下这个基点位于元素的中心
> 可以使用`transform-origin`属性来改变该元素的基点
> 这个属性的值可以是1~3个 , 可以使用长度值 百分比 关键字( 如top left等 )

View File

@ -0,0 +1,76 @@
---
title: CSS动画(2)-transition
date: 2018-5-12 18:16:24
tags:
- 前端
- css
categories:
- 前端杂烩
---
CSS的`transition`允许CSS的属性值在一定的时间区间内平滑地过渡
这种效果可以在鼠标点击 获得焦点 或对元素的任何改变中触发
并圆滑的以动画效果改变CSS的属性值
<!-- more -->
**语法**
transition本身也是一个复合属性 , 主要包含4个属性值
1. 执行变换的属性 `transition-property`
2. 变换延续的时间 `transition-duration`
3. 在变换时间内 , 变换的速率变化 `transition-timing-function`
4. 变换的延迟时间 `transition-delay`
对于多组值 , 它们之间使用逗号分隔
#### transition-property
用来指定哪个CSS属性在变换的过程中应用动画效果
可以取值 `none` , `all` 或者具体的属性名称
all代表任何可以实现动画变换的属性 , 在变换时都会应用动画效果 , 它是默认值
#### transition-duration
用于指定元素转换过程的持续时间 , 单位可以是`s`或者`ms`
例如 0.5s , 或者也可以写作 .5s
默认值为0
#### transition-timing-function
这个属性值的本身是一个**贝塞尔曲线**
有几个预定义的值 , 或者也可以自定义一个曲线
![cubic bezier](/images/前端杂烩/animation/cubic-bezier.png)
如图所示 , 起点和终点也就是P<sub>0</sub>和P<sub>3</sub>的位置是固定的
只需要指定P<sub>1</sub>和P<sub>2</sub>的坐标 , 即可决定该曲线的曲率变化
曲线上每个点的切线斜率代表在该时间点的变换速率
P<sub>1</sub>(x1,y1)
P<sub>2</sub>(x2,y2)
所以自定义贝塞尔曲线的方式就是 `cubic-bezier(x1,y1,x2,y2)`
当然x的值需要在[0,1]的区间内 , 否则无效
y的值可以超过1或者小于0 , 比如构造一个来回的缓冲效果
![贝塞尔曲线](/images/前端杂烩/animation/bezier.png)
预定义的贝塞尔曲线
1. **ease**逐渐变慢默认值ease函数等同于贝塞尔曲线(0.25, 0.1, 0.25, 1.0).
2. **linear**匀速linear 函数等同于贝塞尔曲线(0.0, 0.0, 1.0, 1.0).
3. **ease-in**(加速)ease-in 函数等同于贝塞尔曲线(0.42, 0, 1.0, 1.0).
4. **ease-out**减速ease-out 函数等同于贝塞尔曲线(0, 0, 0.58, 1.0).
5. **ease-in-out**加速然后减速ease-in-out 函数等同于贝塞尔曲线(0.42, 0, 0.58, 1.0)
#### transition-delay
指定一个动画开始的延迟时间 , 默认为0
> 补充说明 :
> 在transition当中 , 这4个单属性值其中的每个都是可以省略的
> 但通常不会省略持续时间 , 因为省略之后就看不到动画的效果了
----
#### 兼容性
为了兼容旧版本的浏览器 , 我们通常需要给transition属性加上前缀
```css
box {
-moz-transition:color 0.5s ease-in;
-webkit-transition:color 0.5s ease-in;
-o-transition:color 0.5s ease-in;
transition : color 0.5s ease-in;
}
```
或者也可以使用**postcss**这种预处理工具 , 来自动添加属性的前缀

View File

@ -0,0 +1,91 @@
---
title: CSS动画(3)-animation
date: 2018-5-12 18:19:07
tags:
- 前端
- css
categories:
- 前端杂烩
---
使用上一节提到的transition已经可以实现相对简单的一些动画效果
但是对于相对复杂一些的效果 , 尤其是其中需要分为多个阶段的 , 就难以实现
CSS3的animation属性 , 就提供了更加强大的动画设计功能
<!-- more -->
#### @keyframes
这个词的意思是`关键帧`
与flash当中的动画制作一样 , 要设计一个完整的动画 , 需要定义其中的几个关键节点的样式
再去自动产生这些节点之间的平滑过渡效果
CSS当中以动画开始的点为`0%` , 以动画结束的点为`100%`
我们可以尝试去定义一组关键帧
```css
@keyframes ANI { /*指定该组关键帧的名称*/
0% {
width : 100px;
background-color:#629411;
}
50% {
width : 150px;
background-color: darkgoldenrod;
}
100% {
width : 250px;
background-color: lightgreen;
}
}
```
0% 也可以写作 `from`
100% 也可以写作 `to`
定义之后我们就可以在DOM元素上调用这组关键帧 , 用来创建动画了
```css
.animation_div {
/* 就是之前定义的关键帧名称 */
animation-name : ANI;
/* 动画持续的时间 */
animation-duration : 5s;
/* 和transition-timing-function一样 */
animation-timing-function : ease-in-out;
/* 动画延迟时间 */
animation-delay: 0.5s;
/* 定义循环次数infinite为无限次 */
animation-iteration-count: 3;
/* 动画执行的方向 */
animation-direction: alternate;
/* 当前动画正在播放(running)或者暂停(paused) */
animation-play-state : running;
}
```
当然动画效果也可以放在`:hover`等伪类当中 , 以创建响应式的效果
前面几项都没什么特别的 , 最后两个属性简单说明一下
#### animation-direction
可以取以下几个值
+ **normal**
每次都正向运行动画,这是默认属性。
+ **alternate**
动画交替反向运行反向运行时动画按步后退同时带时间功能的函数也反向比如ease-in 在反向时成为ease-out。
反向动画同样计入次数
例如次数指定为3 , 那么实际就是正向1次 -> 反向1次 -> 正向1次
+ **reverse**
每次都反向运行动画
+ **alternate-reverse**
与alternate的区别是 : 首次是反向动画
#### animation-play-state
控制当前元素上的动画播放与暂停
暂停之后会定格在当前播放的进度上 , 类似于播放器的暂停
我们可以使用一些伪类 , 或者是JS来控制这个属性 , 从而改变动画的播放状态
比如
```css
.animation_div:hover {
animation-play-state : paused;
}
```
这样可以实现指向该元素的时候暂停动画的播放
> **补充说明**
> 1. 由于每个元素上都可以包含多个动画 , 所以上述的每个属性的取值都可以是单值或者多值
> 2. 可以使用animation这个复合属性来涵盖上面的这些单属性
> ![animation属性](/images/前端杂烩/animation/animation-pro.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB