基本概念
1.服务端提供了 rest风格 api提供访问,简单来说,可以通过http请求访问 es
2.Index(索引)
1.v. == insert一条数据
n. == 库
这两个都会在 每次操作完 响应的 元数据 json数据中出现
index在 json串的最前面 代表 这次操作时 insert操作
insert 在后面以 _index: 出现,代表此次操作的 which 库
3.type(类型) == table
4.document : == 一条数据(json格式的)
1.document的 key == mysql一条记录的 列(字段)
2.document的 value == mysql每个字段的值
元数据
5."_id" : 每条记录 都有一个 唯一标识,当无法判断是更新,还是insert操作的时候,看展示的_id,有没有变化,
有就是insert了一条新记录,没有就是 更新操作
还有可能是 没有执行更新/insert操作
6."_version": 代表这条记录的版本号(根据版本号,可以得知此记录是否被修改过,修改一次,版本号就会变化一次)
7."_source": json记录本体信息
8."_seq_no": 并发控制字段,每次更新+1,用来做乐观锁
应用:在 更新请求后加上 ?if_seq_no = 此时记录的 seq_no & if_primary_term = 此时记录的 primary_term
这时如果,更新操作的时候,如果记录的 _seq_no != if_seq_no 的值,那么无法更新
这样当两个请求,同时操作这条记录的时候,一个请求已经更新了记录,那么 _seq_no + 1,下一个请求就无法 完成更新操作了
9."_primary" 集群,主分片重新分配,如重启,就会变化
倒排索引(类似于 mysql 的索引表,便于查询)
1.es中真正的 json数据 存在 es中的 index下的 type中
然后 在 倒排索引表中(按倒排索引规则 存 索引信息,便于查询)
2.倒排规则:词 与 记录
Es中的数据都是来自于 mysql , 用es的目的 不是 来持久化 数据的,而是因为 它的 数据检索,复杂数据分析 的效率极高,用它来完成 检索,分析的功能
Es的请求,和响应的 json数据(元数据)
1.不简简单单是 document的 json数据,还有很多元数据
根据这些展示的 元数据,我们可以得知 我们 操作es的 情况
2.元数据(以“_”开头的)
{
"_index": , 代表操作的哪个 index(库)
"_type": , 代表操作的哪个 type(表)
"_id": , 每条记录 都有一个 唯一标识,当无法判断是更新,还是insert操作的时候,看展示的_id,有没有变化,
有就是insert了一条新记录,没有就是 更新操作
还有可能是 没有执行更新/insert操作
"_version": , 代表这条记录的版本号(根据版本号,可以得知此记录是否被修改过,修改一次,版本号就会变化一次)
"_source": , json记录本体信息
"_seq_no": , 并发控制字段,每次更新+1,用来做乐观锁
应用:在 更新请求后加上 ?if_seq_no = 此时记录的 seq_no & if_primary_term = 此时记录的 primary_term
这时如果,更新操作的时候,如果记录的 _seq_no != if_seq_no 的值,那么无法更新
这样当两个请求,同时操作这条记录的时候,一个请求已经更新了记录,那么 _seq_no + 1,下一个请求就无法 完成更新操作了
"_primary": , 集群,主分片重新分配,如重启,就会变化
}
3.代表 此次操作的类型的有 index(插入insert) ,create ,delete ,update
初步检索
1._cat
GET /_cat/nodes: 查看所有节点(集群)
GET /_cat/health: 查看 es 的健康状况
GET /_cat/master: 查看主节点
GET /_cat/indices: 查看所有索引
2.(保存)索引一个文档
PUT:(必须带id)
1.PUT /index/type/ 唯一记录id
json数据
注意:当PUT的记录 id,在 es中已经存在,那么 PUT就是 更新操作
POST:(可以带 id , 也可不带 id)
1.(带id)
POST /index/type/ 唯一记录id
json数据
注意:当POST的记录 id,在 es 中已经存在,那么 POST就是 更新操作
2.(不带 id)
POST /index/type
json数据
注意:每次 保存操作,都会生成一个 唯一记录id,不会有更新操作
3.查询一个 document
GET /index/type/id
4.更新一个 文档
1.除了 POST和PUT 带上 id 保存(若 es中 有相同id),就是更新操作外
(更新操作一定会发生)
2.POST index/type/唯一id/_update
{
"doc":{json}
}
注意:这种情况,只要更新的id的 json和es中的相同,那么不会进行更新操作,简单来说就是版本号不会改变
5.删除文档/索引(没有删除 type)
1.DELETE index/type/id
2.DELETE index
6.bulk 批量 API
1.语法格式:
POST index/type/_bulk
{action:{metadata}}\n (什么类型的操作,对哪个记录操作)
{ request body}\n 真正的json数据
例如:
{"index" : {"_id" : "1"}}
{json数据}
保存一个 id为1 的 document
进阶检索
1.uri + 请求参数(基本不用)
2.Query DSL( uri + 请求体 检索)
GET /index/_search (没有指定 type , 只指定 index)
DSL (json) 检索条件
·(注意:在postman中,只能用 POST + 请求体,但是在es客户端,可以用 GET + 请求体)
Query DSL(检索规则都是,分词检索,按评分排序)
1.格式
{
查询条件名:{
argument:value,
argument:value...
}
}
例子:
{
"query":{
"match_all":{}
},
"sort":{
"字段":desc
}
"from":0,
"size":5,
"_source":[字段1,字段2 ]
}
2.match 匹配查询(都是模糊匹配 包含即可)
1.基本类型 精确匹配(实际也不叫精确匹配)
{
"query":{
match:{
"account_num":20
}
}
}
match 返回 account_num = 20的
但是注意:非全文检索(精确检索),我们不用match,用 term,term表示 记录里面的字段值 = term里面的值
2.字符串,全文检索(分词匹配,按评分排序,全要)
{
"query":{
"match":{
"address": "mill wiio"
}
}
}
match,分词匹配,将 mill 和 wiio 拆开,然后看评分排序,全要,最后只要包含 mill 或 wiio 的记录 全部要
3.match_pharse【短语匹配】(都是模糊匹配 包含即可)
将需要匹配的值当成一个整体单词(不分词)进行检索
{
"query":{
"match_pharse":{
"address": "mill wiio"
}
}
}
查出 address 中 包含 (mill road) 的所有记录,并给出相关性得分
不分词
4.multi_match 【多字段匹配】,也是分词匹配(都是模糊匹配)
就是字段匹配 or 字段匹配,或者的关系
{
"query":{
"multi_match":{
"query": "mill wiio" 匹配条件
"fields": ["state","address"] 匹配字段
}
}
}
state 或者 address 包含 mill or wiio的,按评分排序,全要
5.bool 【复合查询】
复合查询 可以合并 任何 其他的查询语句,包括复合语句
1. must: 必须达到 must列举的条件(must里面的条件是 and拼接)
2. must_not: 必须不是(must_not里面的条件是 and 拼接)
3. should: 可以是也可以不是,是的评分更高(should里面的条件是 and 拼接)
{
"query":{
"bool":{
"must": [
{"match":{"address": "mill wiio"},
{"match":{"gender": "M"},
]
}
}
}
bool后面的条件都是 and拼接
注意:must_not不会计算相关性得分,must和should会计算相关性得分
6.filter
filter = must 但是它不会进行 相关性得分,只是起过滤作用
7.term(精确匹配的)
{
"query":{
"term":{
"age": "15"
}
}
}
这个和上面的 match组合的区别,这是不分词,且精确匹配的
检索匹配分 是否分词,以及是否是精确匹配
1.match 模糊匹配,分词,算得分
2.match_parse 模糊匹配,不分词,算得分
3.multi_match 模糊匹配,分词,算得分 (用 or 连接 不同字段的条件)
4.must / should 模糊匹配,分词,算得分(用 and 连接 不同的 match)
5.must_not /filter 模糊匹配,分词,不算得分(用 and 连接 不同的 match)
6.term(与 match对比)精确匹配,不分词,算得分
7.用 match 但是 字段.keyword : ? , 那么这时精确匹配,不分词,算得分
must/must_not/should/filter 都是来复合组合 各种match/term的,并且这些 match都是 and拼接
但是 multi_match 是用 or 连接 字段条件的
检索后的 分析功能(aggs)
1.格式
DSL
{
"query":{}
"aggs":{
"自定义聚合分析的name1":{
"聚合类型":{filed:"" , size:""}
例如"avg":{filed:"age",size:"5"} 求age的 平均值
"aggs":{子聚合}
},
"自定义聚合分析的name2":{
"聚合类型":{filed:"" , size:""}
}
}
}
2.结果展示
1.query 先展示 hit命中结果
2."aggregations" 然后展示 聚合分析的结果
"aggregations":{
"自定义聚合分析的name1":{
bucket展示 聚合结果
"aggs":{子聚合}
},
"自定义聚合分析的name2":{
"聚合类型":{filed:"" , size:""}
}
}
es的映射(实际就是记录字段的 类型)先不研究
es的分词器(自带的有很多,一般是用的标准分词器)
1.自带的 只能分词 英文(分词规则,也是自带的)
2.下载 ik分词器,可以分词中文(但是还得,自定义分词规则)
es 在7版本后不支持 type了,就是index -> document了,以后crud都不要带上type即可
springboot整合es
1.导入依赖
2.手动将 RestHighLevelClient 注入 ioc容器中
3.在 es的配置类中,用Static静态代码块,添加 requestOptions 请求设置项(设置一些请求的 信息,例如header头信息等等,安全等等)
具体配置百度即可
4.然后,利用各种 DSLAPI, 去构建条件,封装api,然后 使用RestHighLevelClient(构造条件),去访问
es,获得 response
es的数据全部存在 内存中
从mysql查出各种表的数据,组合成json,存到es,这个过程的问题
1.存有用的数据,因为es是内存存储,贵,容量小
2.mysql 拼接的 json数据可能存在 冗余数据,要处理
例如:es中每条记录中都有 attrs 规格参数(很多都是相同的)
1.浪费空间 每条记录都带上 attrs
2.浪费时间(多 index 一个 attrs 索引,并存spuId 和 记录索引 联系起来)
相当于 每次检索 都是 检索 2个 index ,当并发量一大时间会长
最好浪费 空间,不要浪费时间,空间的浪费,可以加内存条
es 的 nested类型
1.key是数组类型,并且数组里存的也是 json对象类型,要用 nested类型,不然会扁平化处理
要为 es 准备一个服务,而且我们要在,common里面定义一个 javabean,用于 mysql和es的数据类型对应,简单来说就是给 es 传 javabean,然后es保存,es查询的json也存在javabean中响应页面
keyword类型,就是数字类型,精确匹配