简称es,是类似于mysql但是专注于搜索的一种数据库。在elastic stack中占据重要地位。
倒排索引:
我们的数据库都是正向索引,比如根据id查询数据,那么倒排索引是将关键字进行分词,然后将词条和id保存在一张表中,不同数据分词后有相同的词条的话,就会记录在同一条数据中,并且把id放在一个字段,搜索的时候根据词条先搜索出符合的id,然后根据id查询数据。
分词器:
进去之后点击右边的版本,就能进去下载,
#因为启动es时候 已经做好的目录挂载
容器内部:/usr/share/elasticsearch/plugins
宿主机:/mydata/elasticsearch/plugins所以只需要将文件复制到/mydata/elasticsearch/plugins 目录下即可
然后重启es
docker restart elasticsearch
分词器也就是分词的规则,es中有默认的细粒度分词(ik_max_word
)和粗粒度分词(ik_smart
),细粒度分词比较多,粗粒度分词比较少。
我们也可以自定义我们想要分出来的词和不想被分出来的词,比如我们自己创建的一个品牌名,就可以自己定义一个分词字典,同样的,不想分词的也会有一个字典。
想要分出的词就可以写在我们配置文件中的ext.dic字典,不想分出来的就修改sropword.dic字典。
mapping 属性
mapping属性实际上就是我们mysql中的一个表结构,比如某个字段是什么类型的啊,有什么约束条件啊什么的。
每创建一个字段都要想下图中的几个条件,什么类型的,是否参与搜索(根据这个判断是否创建倒排索引,默认index为true),使用什么分词器,该字段有没有子字段。
索引:
索引其实对应的就是mysql中的表,es说要创建个索引,就相当于mysql说,要创建一个表。
创建索引示例:
查看和删除索引:
修改索引库:
实际上es是不支持修改索引库的,因为带来的影响比较大,尤其是生产环境下。
但是,虽然不支持修改索引库,但是支持添加一个字段
文档:
文档,实际上就相当于mysql中的数据。添加文档就是mysql中的添加数据
这里要说一下,mysql中写的语句叫做sql语句,es中写的语句叫做DSL语句。
新增文档:
查看和删除文档:
修改文档:
修改文档实际上有两种方法,一种是全量修改,一种就是新增一个文档:
方式一:他会根据id先找到这个文档,然后删除,再添加新文档
方式二, 这个就是修改指定的字段,我们可以看到上面的_doc变成了_update ,所以这里就是对某个字段进行修改了
es查询语句:
查询所有:
这里的查询类型,之后可以根据自己的条件的不断变化,更换不同的查询类型,这里的math_all就是查询所有,所有里面不需要跟条件
全文检索查询:
设定的场景就是我们常见的搜索框,根据输入的字段查询匹配的数据。
match是查询某一个字段中是否包含输入的信息,multi_match是同时查询几个字段中是否包含输入的信息。
注意:搜索字段越多,查询效率越低,所以我们尽量用一个字段查,之后会学到copy_to,查询一个字段也可以实现多个字段的效果。
精确查询:
这里指的就是不被分词的字段,进行精确匹配 ,也就是keyword
包括term和range: range中gte是大于等于,lte是小于等于 greate/less than equals
地理查询:
也就是根据经纬度查询:
第一种,就是geo_bounding_box类型,根据传入的两个经纬度确定两个点,然后分别画横竖两条线,然后围成一个矩形,那么查询出来的结果,就是经纬度在这个矩形当中的数据。
第二种就是geo_distance,这个比较常用,它是根据传入的一个经纬度点和一个距离,以经纬度点为圆心,以距离为半径画圆,查出来的就是经纬度在这个范围中的数据。适合场景,附近的人。
注意,那个距离要写单位.比如:km m
` 那个经纬度的点是要数据中有个字段,专门表示经纬度,然后用那个字段的名称,然后后面的值进行修改,图中的字段名称就叫做location (lat 经度 lon 纬度 )
可以分开写,也可以像第二张图中一样用逗号隔开
复合查询:
相关性算分:这里要明白一个道理就是es会根据匹配度进行数据打分_score,匹配度越高,排序越靠前,并且这个算分可以人工干预。
Function_score_query:根据这个就可以给我们想要加分的数据进行人工干预。
Boolean Query:
这种复合查询就是相当于多条件查询,相当于mysql中的and or
每个关键字都可以定义多个查询条件
排序:
两种排序,一种是按照字段的值的大小进行升序或者是降序的排序,这种就是常见的大小排序
另一种是根据在某个经纬度的多少距离内的远近排序。这种就是查询附近的酒店那个意思
那么要注意的是,一旦做了排序,那么原来的那个相关性打分就没意义了,所以_score这个字段就变成了null
也可以在排序中写两个,表示当第一个相等时,就按第二个条件进行排序。
分页:
在es中分页和mybatis中的也差不多,也是根据页数和每页条数进行,在es中的关键字是from 和size
深度分页问题:
比如这个图中,从9990查询,查十条是正好10000条的,是不会报错的,但是如果改成9991就会变成10001条,超过了我们的结果集查询上限,那么就会报图中的错。
解决的办法就是下面两种,第二种不推荐使用,第一种也有不好的地方,只能往后查,不能往前查。
分页小结:
高亮处理:
就是我们的百度的时候,我们查询出来的东西都变成了红色。
这里涉及到我们的搜索字段要和高亮字段匹配才能进行高亮,那么如果使用copy_to之后的那个包含了多个字段信息的字段怎么办呢,我们可以手动设置搜索字段和高亮字段不匹配。
就是图中红色框框起来的这段配置。
小结:
数据聚合:
也就是相当于mysql中的group by进行分组之后进行聚合函数。聚合的字段一定是不分词的。
大致分这么几种,当然还有更多,可以查看es的官方文档
小结:
利用这个值进行聚合,下面的terms就是这个聚合。
aggs就是DSL语句中聚合的表示。
查询出来的结果就是一个这样的json格式:buckets就是我们聚合之后的结果,buckets中每一个{}就是一个bucket(桶),doc_count就是这个聚合之后桶内的文档数量,默认是倒序排序
如果修改默认的聚合排序规则,只要加一个order字段,然后对其进行排序即可
限定聚合范围:
只需要添加一个查询条件就可以,就相当于msyql中group by前面的where
小结:
Metrics聚合方式:也不能算是另一种,就是一部分,也相当于mysql中的max min avg sum等
下图中用了一个聚合的嵌套,外面使用了桶聚合,然后在桶聚合中的每一个桶内,使用了Metrics聚合
添加之后,查询的结果中,每一个桶内就多了几个结果;
如果想对这个结果中的avg的值进行一个排序,那么就要添加order: desc 降序 asc生序
copy_to:
当我们在做query_string查询的时候 关联多个字段查询3
可以利用copy_to属性完成将多个字段拷贝到一个属性中 简化查询
PUT user
{
"mappings": {
"properties": {
"first_name": {
"type": "text",
"copy_to": "full_name"
},
"last_name": {
"type": "text",
"copy_to": "full_name"
},
"full_name": {
"type": "text"
}
}
}
}
总结:
1.copy_to属性可以帮助我们将多个字段或者一个字段拷贝到另外一个字段
2.copy_to属性可以帮助我们简化查询
3.copy_to属性可以帮助我们提高查询速度
自动补全:
拼音分词器,自动补全要依赖于拼音分词器,提升用户体验
步骤:
1.解压
2.上传到es的插件目录下 就是上面方分词器的那个目录
3.重启es
自定义分词器
默认的拼音分词器会将每个汉字单独分为拼音,而我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。
elasticsearch中分词器(analyzer)的组成包含三部分:
character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart
tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等
文档分词时会依次由这三部分来处理文档:
声明自定义分词器的语法如下:
PUT /test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "ik_max_word",
"filter": "py"
}
},
"filter": {
"py": {
"type": "pinyin",
"keep_full_pinyin": false,
"keep_joined_full_pinyin": true,
"keep_original": true,
"limit_first_letter_length": 16,
"remove_duplicated_term": true,
"none_chinese_pinyin_tokenize": false
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "my_analyzer",
"search_analyzer": "ik_smart"
}
}
}
}
注意: 拼音分词器适合在创建倒排索引的时候使用,但不能再搜索的时候使用,因为会有拼音相同汉字不同的情况出现。
为避免这种情况,所以我们再创建索引的时候要给字段设置,创建倒排索引的时候使用什么分词器,搜索的时候使用什么分词器。
小结:
自动补全,我们的重点来了:
1、自动补全的字段类型是completion,
2、自动补全的字段应该是一个多个词条形成的数组,也就是我们的copy_to的目标字段
自动补全的语法:
查询结果就是我们的suggest对象,其中的options包括自动补全后的所有信息:
数据同步:
思路分析
常见的数据同步方案有三种:
-
同步调用
-
异步通知
-
监听binlog
方案一:同步调用
基本步骤如下:
-
hotel-demo对外提供接口,用来修改elasticsearch中的数据
-
酒店管理服务在完成数据库操作后,直接调用hotel-demo提供的接口,
方案二:异步通知
流程如下:
-
hotel-admin对mysql数据库数据完成增、删、改后,发送MQ消息
-
hotel-demo监听MQ,接收到消息后完成elasticsearch数据修改
方案三:监听binlog
流程如下:
-
给mysql开启binlog功能
-
mysql完成增、删、改操作都会记录在binlog中
-
hotel-demo基于canal监听binlog变化,实时更新elasticsearch中的内容
小结:
方式一:同步调用
优点:实现简单,粗暴
缺点:业务耦合度高
方式二:异步通知
优点:低耦合,实现难度一般
缺点:依赖mq的可靠性
方式三:监听binlog
优点:完全解除服务间耦合
缺点:开启binlog增加数据库负担、实现复杂度高