开源搜索引擎,for search
开箱即用:localhost:9200
开发:产品基本功能,底层原理
运维:
方案:解决大数据搜索的解决方案
elastic认证工程师。
内容:入门、集群管理、大数据分析、实战
近实时
分布式 存储/搜索/分析引擎
Solr(Apache)
Splunk
多编程语言类库
RESTful API
功能:搜索、聚合
Lucene 7.x
D:\elasticsearch-5.6.9\bin>elasticsearch-plugin install analysis-icu
- 查询插件 :进入es安装目录的
D:\elasticsearch-5.6.9\bin>elasticsearch-plugin list
localhost:9200/_cat/plugins
节点名称-集群名称-存放数据地址
bin/elasticsearch -E node.name=node1 -E cluster.name=geektime -E pah.data=nod1e_data -d
bin/elasticsearch -E node.name=node2 -E cluster.name=geektime -E pah.data=node2_data -d
bin/elasticsearch -E node.name=node3 -E cluster.name=geektime -E pah.data=node3_data -d
kibana汉化配置
在kibana.yml文件最后一行加
注:5.6.9版本过低,无法通过配置汉化,只能下载汉化包汉化
i18n.locale: "zh-CN"
下载:https://www.elastic.co/cn/downloads/past-releases/logstash-5-6-9https://www.elastic.co/cn/downloads/past-releases/logstash-5-6-9
使用:解压后cmd进入\bin目录使用
bin/logstash -e 'input { stdin { } } output { stdout {} }'
直接输入helloworld
样例:movielens.csv文件,配置config文件,将文件处理后输出到es的端口
设置分片数量和副本数量:
方案1:创建索引的时候设置
PUT twitter
{
"settings" : {
"index" : {
"number_of_shards" : 3,
"number_of_replicas" : 2
}
}
}
方案2:创建Mapping的时候设置
PUT test
{
"settings" : {
"number_of_shards" : 1
},
"mappings" : {
"type1" : {
"properties" : {
"field1" : { "type" : "text" }
}
}
}
}
Analyzer组成:
ElasticSearch内置分词器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6rbb893l-1615873812134)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210311095203138.png)]
中文分词:
在elasicsearch的插件中下载ICU Analyzer
Elasticsearch-plugin install analysis
从gitthub中下载IK分词器
https://github.com/medcl/elasticsearch-analysis-ik
THULAC分词器(清华大学)
https://github.com/microbun/elasticsearch-thulac-plugin
DSL:
查询所有数据:
GET /_search
查看集群健康信息
GET /_cat/health?v
查看集群中节点信息
GET /_cat/nodes?v
查看集群中索引信息
GET /_cat/indices?v
简化:
GET /_cat/indices?v&h=health,status,index
创建索引
PUT /baizhi
删除索引
DELETE /baizhi
ES为了搜索提供了两大类api:URL search 和 Request Body Search
ElasticSearch查询返回结果各个字段的含义
GET /_search
结果略。从上到四个返回值,took,timed_out,_shards,hits。
curl -XGET http://localhost:9200/kibana_sample_data_ecommerce/_search?q=customer_first_name:Eddie
指定字段查询 / 泛查询
q=title:2012 / q=2012
GET /movies/_search?q=2012&df=title
{
"profile":"ture"
}
// 泛查询,正对_all,所有字段
GET /movies/_search?q=2012
// 指定字段
GET /movies/_search?q=title:2012
{
"profile":"true"
}
Type:Disjunction Max Query:分离最大化查询:将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回。弥补bool查询的不足
TermQuery:分词精确查询,如:查询hotelName分词后包含hotel的term文档
QueryBuilders.termQuery("hotelName","hotel")
QueryBuilders.termsQuery("hotelName","hotel","test")
// 使用引号,parase
```dsl
GET /movies/_search?q=title:"Beautiful Mind"
{
"profile":"true"
}
```
```dsl
GET /movies/_search?q=title:Beautiful Mind
{
"profile":"true"
}
```
```dsl
GET /movies/_search?q=title:(Beautiful Mind)
{
"profile":"true"
}
```
- 分组与引号:
注:profile API 是 Elasticsearch 5.x 的一个新接口。通过这个功能,可以看到一个搜索聚合请求,是如何拆分成底层的 Lucene 请求,并且显示每部分的耗时情况。
可以通过在 query 部分上方提供 “profile: true” 来启用Profile API。
{
"query":{
"bool":{
"must":[
],
"should":[
],
"must_not":[
],
"filter":[
],
"minimum_should_match":0
}
}
}
- 布尔与分组
GET /movies/_search?q=year:>190
{
"profile":"true"
}
GET /movies/_search?q=title:b*
{
"profile":"true"
}
“match_all”:{} :匹配所有文档
// 对日期进行排序
POST kibana_sample_data_ecommerce/_search
{
"sort":[{"order_date":desc}],
"query":{
"match_all":{}
}
}
POST kibana_sample_data_ecommerce/_search
{
"_source":[order_date"],
"query":{
"match_all":{}
}
}
"script": {
"lang": "...",
"source" | "id": "...",
"params": { ... }
}
lang:代表language脚本语言,默认指定为:painless。
source:脚本的核心部分,id应用于:stored script。
params:传递给脚本使用的变量参数。
短语搜索 - Match Phrase:和match查询类似,match_phrase查询首先解析查询字符串来产生一个词条列表。然后会搜索所有的词条,但只保留包含了所有搜索词条的文档,并且词条的位置要邻接。
“slop”:1表示短语中单词之间可以有一个其他字符
PUT movies{
"mapping":{
// define your mappings here
}
}
自定义分词器
当ES自带的分词器无法满足时自定义分词器,实现:通过自组合不同的组件实现。
ES中默认的Character Filters(字符过滤器):在Tokenizer之前对文本进行处理,例如增加删除及替换字符,可以配置多个Character Filter,但这样会影响Tokenizer的Position和offset信息
一些自带的Character Filter: HTML strip(去除html标签),Mapping(字符串替换)、Pattern replace(正则匹配替换)
Index template定义在创建新index时可以自动应用的settings和mappings
Dynamic template根据ES自动识别的数据类型,结合字段名称,动态设定字段类型
ES除搜索之外,提供了针对ES数据进行统计分析的功能(Aggregation)
集合的分类
Metric :对应SELECT COUNT(brand) from cars,一些系列的统计方法
Answer:
8. Match中terms之间是or的关系,Match phrase的terms之间是and的关系,并且term之间的位置关系也会之间影响搜索的结果
9. slop
10. 直接报错
11. 文档被索引,新增的字段在_source中可见,但是该字段无法被搜索
12. 错,字段类型修改,需要reindex操作
13. 对,在Mapping文件中可以为indexing和searching指定不同的analyzer
范围查询:rang
query filter term搜索对文本不分词,直接拿去倒排索引匹配,你输入的是什么就去匹配什么
上例中,title和body互相竞争:不应该将分数简单叠加,而是应该找到单个最佳匹配的字段的评分
icu
pinyin
search template:"{{field}}" : "{{value}}"
GET /blog_website/blogs/_search/template
{
"inline" : {
"query": {
"match" : {
"{{field}}" : "{{value}}"
}
}
},
"params" : {
"field" : "title",
"value" : "博客"
}
}
相当于
GET /blog_website/blogs/_search
{
"query": {
"match" : {
"title" : "博客"
}
}
}
注:当算分差别非常大的时候,可以通过Modifier平滑曲线
Boost Mode 和Max Boost
一致性随机函数
让每个用户能看到不同的***随机排名***,对于同一用户的访问,结果的相对顺序保持一致
只要“seed”的值不变,搜索的结果相对顺序保持一致
Term suggester mode
- 过程:用户输入一个错误的拼写到指定字段搜索,当搜索不到时会根据suggest-mode返回建议的词
Completion Suggester:提供了自动完成的功能。用户每输入一个字符,就需要即时发送一个查询请求到后段查找匹配项。
注意:对性能要求苛刻,ES采用了不同的数据结构,并非通过倒排索引来完成,而是将Analyze的数据编码成FST和索引一起存放。FST会被ES整个加载进内存,速度很快。
FST只能用于前缀查找。
解释:FST是lucene中用来存储字典,并进行检索的核心数据结构,FST本质上是一个比HashMap有更强大功能keyvalue存储结构
使用步骤:
水平拓展痛点:
单集群:水平拓展时,节点不能无限增加。因为当集群的meta信息过多,会导致更新压力变大,单个Active Master会成为性能瓶颈,导致整个集群无法工作
跨集群搜索:Cross -cluster search,ES5.3引入
允许任何节点扮演federated节点,以轻量的方式,将搜索请求代理。
不需要以client node的方式加入
ES分布式架构:
Coordinating Node:处理请求的节点,索引节点都默认是此节点通过将其他类型设置为false.使其成为Dedicated Coordinating Node
Data Node : 可以保存数据的节点,节点启动后默认就是数据节点,通过设置node.data:false禁止
Data Node的职责:保存分片数据,由Master决定如何把分片分发到数据节点上。通过增加数据节点,可以解决数据水平拓展和解决数据单点问题。
集群状态信息(cluster state)保存有
shard=hash(_rounting)%number_of_primary_shards
不能修改Primary的原因是因为文档到分片的路由算法是由主分片数计算出来的
问题1:为什么ES的搜索是近实时的?
Refresh频率默认1s/次
问题2:ES如何保证断电时数据也不丢失?
问题3:为什么删除文档,并不会立刻释放空间?
删除的文件保存在.del文件中,flush才会被彻底删除
倒排索引不可变性
倒排索引一旦生产,不可更改。
好处:
通过_version版本号的方式进行乐观锁并发控制
在es内部第次一创建document的时候,它的_version默认会是1,之后进行的删除和修改的操作_version都会增加1。可以看到删除一个document之后,再进行同一个id的document添加操作,版本号是加1而不是初始化为1,从而可以说明document并不是正真地被物理删除,它的一些版本号信息一样会存在,而是会在某个时刻一起被清除。
es提供了一个外部版本号的乐观控制方案来替代内部的_version:
?version=1&version_type=external
"aggregations" : { // 表示聚合操作,可以使用aggs替代
"" : { // 聚合名,可以是任意的字符串。用做响应的key,便于快速取得正确的响应数据。
"" : { // 聚合类别,就是各种类型的聚合,如min等
<aggregation_body> // 聚合体,不同的聚合有不同的body
}
[,"aggregations" : { [<sub_aggregation>]+ } ]? // 嵌套的子聚合,可以有0或多个
}
[,"" : { ... } ]* // 另外的聚合,可以有0或多个
}
-注:聚合是和查询同等级的
例:
curl -XPOST "192.168.1.101:9200/student/student/_search" -d
'
{
"query": { // 可以先使用query查询得到需要的数据集
"term": {
"classNo": "2"
}
},
"aggs": {
"min_age": {
"min": {
"field": "age"
}
}
}
}
'
支持对聚合分析的结果,再次进行聚合分析;
Pipeline 的分析结果会输出到原结果中,根据位置的不同,分为两类
Sibling - 结果和现有分析结果同级
Parent - 结果内嵌到现有的聚合分析结果之中
例1:平均工资最低的工资类型 | sibling Pipeline
POST employees/_search
{
"size": 0,
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword",
"size": 10
},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
}
}
},
"min_salary_by_job":{
"min_bucket": {
"buckets_path": "jobs>avg_salary"
}
}
}
}
POST employees/_search
{
"size": 0,
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword",
"size": 10
},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
}
}
},
"avg_salary_by_job":{
"avg_bucket": {
"buckets_path": "jobs>avg_salary"
}
}
}
}
POST employees/_search
{
"size": 0,
"aggs": {
"age": {
"histogram": {
"field": "age",
"min_doc_count": 1,
"interval": 1
},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
},
"derivative_avg_salary":{
"derivative": {
"buckets_path": "avg_salary"
}
}
}
}
}
}
链接: https://blog.csdn.net/xixihahalelehehe/article/details/114411134.
排序
指定orde,默认情况下按照降序排序
指定size,就能返回相应的桶
ES内部排序
GET /cars/transactions/_search
{
"size":0,
"aggs":{
"popular_colors":{
"terms": {
"field": "color",
"order": { ---表示要对聚合结果做排序
"_count": "desc" ---排序字段是doc_count,顺序是降序
}
}
}
}
}
GET /cars/transactions/_search
{
"size": 0,
"aggs": {
"price": {
"histogram": { ---区间聚合
"field": "price", ---取price字段的值
"interval": 20000, ---每个区间的大小是20000
"order": { ---表示要对聚合结果做排序
"_key": "desc" ---排序字段是桶的key值,这里是每个区间的起始值,顺序是降序
}
}
}
}
}
Terms Aggregation | 返回参数中的 2 个特殊值
Terms Aggregation | 执行流程
注:返回分桶中文档数最大的 3 个分桶;结果不一定准确;
doc_count_error_upper_bound | 举例分析
左边的分片中,选出来的文档数最大的 3 个桶中的文档数分别是:6, 4, 4,那么遗漏的文档数最大可能就是 4;
右边的分片中,选出来的文档数最大的 3 个桶中的文档数分别是:6, 3, 2,那么遗漏的文档数最大可能就是 2(图中有错);
sum_other_doc_count | 举例分析
索引中全部文档数 - 返回的 3 个桶中的文档总数,29 - 22 = 7;
解决 Terms 聚合不准的问题 | 提升 shard_size 的参数
Terms 聚合分析不准的原因:
数据分散在多个分片上,Coordinating Node 无法获取数据的全貌;
解决方法1:
当数据量不大时,设置 Primary Shard 数为 1,实现准确性;
解决方法2:
当数据分布在多个 Primary Shard 上时,设置 shard_size 参数,提升准确性,其原理是:每次从 Shard 上额外多获取数据,提升准确率;
参数 | shard_size | 设定
通过调大 shard_size 的大小,使得 doc_count_error_upper_bound 的值降低,从而提升准确度,其原理是:增加整体计算量,提高精准度的同时会降低响应时间;
shard_size 默认大小
shard_size = size * 1.5 + 10
参考:https://blog.csdn.net/liuhe2296044/article/details/103745740?utm_source=app&app_version=4.5.5
对象 | Nested 对象 | 局限性
每篇博客的文档中,包含作者信息,当作者信息变更时,整个博客文档都需要变更;
Parent & Child
定义父子关系的步骤
文档父子关系实例:
DELETE my_blogs
PUT my_blogs
{
"settings": {
"number_of_shards": 2
},
"mappings": {
"properties": {
"blog_comments_relation": {
"type": "join",
"relations": {
"blog": "comment"
}
},
"content": {
"type": "text"
},
"title": {
"type": "keyword"
}
}
}
}
参考链接:https://blog.csdn.net/weixin_33669968/article/details/106422331?utm_source=app&app_version=4.5.5
重建索引的场景
重建索引的API: Update By Query Reindex
Update By Query :在现有索引上重建
POST 索引/索引类型/_update_by_query
{
"script": {
"source": "ctx._source['修改的字段名'] = '修改后的值'"
},
"query": {
"bool": {
"must": [
{
"term": {
"查询条件此处为字段名": "字段的值"
}
}
],
"must_not": [],
"should": []
}
}
}
查询index索引,type等于index_type中数据满足field=value的数据,修改其中field=test,对应的就是关系型数据库的update set … where…语句;
Reindex:在其他索引上重建索引
Reindex基础实现: _reindex会将一个索引的快照数据copy到另一个索引,默认情况下存在相同的_id会进行覆盖(一般不会发生,除非是将两个索引的数据copy到一个索引中),
POST _reindex
{
"source": {
"index": "my_index_name"
},
"dest": {
"index": "my_index_name_new"
}
}
Elasticsearch可以使用自身的Ingest Pipeline功能进行数据预处理, 无须借助Logstash.
Ingest Pipeline介绍:Ingest Pipeline 就是在文档写入Data Node之前进行一系列的数据预处理, 进行数据预处理的就是processor, 一组处理器构成了Pipeline. 所有的预处理都在Ingest Node上执行, 默认情况下所有节点都是Ingest Node.
- 常用的process
split processor
字符串切分成数组
join processor
数组转化成字符串
gsub processor
字符串替换
set processor
创建或替换一个字段.
remove processor
移除一个字段
rename processor
重命名一个字段
lowercase processor
字符串小写化
upcase processor
字符串大写化
script processor
使用painless脚本进行复杂的处理
语法:
PUT /_ingest/pipeline/my_pipeline_id
{
"description": "to split blog tags",
"processors": [
{
"split": {
"field": "tags",
"separator": ","
}
}
]
}
description是对pipeline的描述, processors定义了一组处理器.
PUT /_ingest/pipeline/my_pipeline_id
{
"description": "to split blog tags",
"processors": [
{
"split": {
"field": "tags",
"separator": ","
}
},
{
"script": {
"source": """
if(ctx.containsKey("content")){
ctx.content_length = ctx.content.length();
}else{
ctx.content_length = 0;
}
"""
}
}
]
}
(2)新增文档
PUT /blogs/_doc/1?pipeline=my_pipeline_id
{
"title": "Introducing big data......",
"tags": "hadoop,elasticsearch,spark",
"content": "You konw, for big data"
}
PUT /blogs/_doc/2?pipeline=my_pipeline_id
{
"title":"Introducing cloud computering",
"tags":"openstack,k8s",
"content":"You konw, for cloud"
}
(3) 查看文档
GET /blogs/_search
(4)结果:
"hits" : [
{
"_index" : "blogs",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"title" : "Introducing big data......",
"content" : "You konw, for big data",
"content_length" : 22,
"tags" : [
"hadoop",
"elasticsearch",
"spark"
]
}
},
{
"_index" : "blogs",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"title" : "Introducing cloud computering",
"content" : "You konw, for cloud",
"content_length" : 19,
"tags" : [
"openstack",
"k8s"
]
}
}
]
- 建模建议(1):如何处理关联关系
注:Kibana目前不支持nested类型和parent/child类型,未来可能会支持。
- 建模建议(2):避免过多字段
- 导致文档中有成百上千的字段原因:
Dynamic VS Strict
建模建议(5):为索引的Mapping加入Meta信息
用户文档信息泄露原因:
Hot Nodes
用于数据的写入,
Warm Nodes
用于保存只读索引
配置Hot & Warm Architecture
ES7.0开始,新建一个索引时,默认创建一个分片
单分片:
集群增加一个节点后,ES会自动进行分片的移动
调整分片总数设定,避免分配不均衡
系统设置
参考官方手册
内存设定计算实例
The index & Query Slow Log
分片没有被分配的一些原因
常见问题与解决方法
Codec Plugin -single Line
6.0以上版本的ElasticSearch直接导入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
6.0以下2版本的ElasticSearch依赖配置
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>transportartifactId>
<version>5.6.9version>
dependency>
<dependency>
<groupId>org.apache.lucenegroupId>
<artifactId>lucene-coreartifactId>
<version>6.6.1version>
dependency>
<dependency>
<groupId>org.apache.lucenegroupId>
<artifactId>lucene-highlighterartifactId>
<version>6.6.1version>
dependency>
<dependency>
<groupId>org.apache.lucenegroupId>
<artifactId>lucene-queriesartifactId>
<version>6.6.1version>
dependency>
注:版本号获取
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NuxCkTIB-1615873812156)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210312112549525.png)]