Elasticsearch、Kibana基础知识

431 阅读4分钟

0. 基本概念

Elasticsearch在数据分析和处理方面强于Mysql,Mysql主要是数据的持久化结构化存储,而在海量数据检索方面Elasticsearch更强。 Es是对Lucene的封装,直接提供Rest Api。

  1. Index 索引 动词:Insert/名词:Database
  2. Type 类型 在Index中,可以定义一个或多个类型,相当于DataBase中的Table。
  3. Document 文档 相当于表中的一条记录

1. Es为什么快? -- 倒排索引

倒排索引:存储数据的时候,先把数据拆分为单词,即“分词”,在倒排索引表中,维护着每个单词所在的记录。在检索关键词的时候就会快速得到包含该关键词的记录,即“文档”。

相关性得分:检索出的所有文档,会根据相关性得分,最终返回检索结果。举一个教程中的例子:

倒排索引表:

单词记录
红海1,2,3,4,5
行动1,2,3
探索2,5
特别3,5
记录篇4
特工5

保存的记录:

1 - 红海行动 2 - 探索红海行动 3 - 红海特别行动 4 - 红海记录篇 5 - 特工红海特别探索

比如检索“红海特工行动”,红海- 特工-行动,三个单词,在倒排索引表中可以看到记录12345记录中都存在,所以第一步是查询到所有的5条记录,或者说5个文档,其中1号记录两个单词全部命中,2、3号记录3个单词命中两个,4号记录两个单词命中1个,5号记录4个单词命中两个,所以相关性得分1号记录胜出,即为最终的结果。

2. docker 安装 es 和 kibana

安装:参考之前的文章,镜像版本号可以自行指定:juejin.cn/post/684490…

这里按照步骤安装:

  1. 创建数据卷
sudo mkdir -p /home/chins/docker/elasticsearch/volume/config
sudo mkdir -p /home/chins/docker/elasticsearch/volume/data
  1. 写入配置,允许任意主机访问(权限不够就切换成root用户)
# 注意这里是k-v之间有空格
sudo echo "http.host: 0.0.0.0" >> /home/ubuntu/volumes/elasticsearch/config/elasticsearch.yml
  1. 启动es容器
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -v /home/chins/docker/elasticsearch/volume/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /home/chins/docker/elasticsearch/volume/data:/usr/share/elasticsearch/data -v /home/chins/docker/elasticsearch/volume/plugins:/usr/share/elasticsearch/plugins -d elasticsearch:7.4.2

如果启动不成功,docker logs查看发现下图,是因为其他用户组的权限不足,这里直接改成777。

chmod -R 777 /elasticsearch/volume/
  1. 启动kibana容器
# elasticsearch容器的ip
docker inspect 03b7f9574290 | grep ip 
docker run -d --name kibana -e ELASTICSEARCH_HOSTS=http://172.17.0.3:9200 -p 5601:5601 -d kibana:7.4.2

3. es基本操作

命令解释
GET _cat/nodes查询所有节点
GET _cat/health查看es集群健康状况
GET _cat/master查看主节点
GET _cat/indices查看所有索引 (show databases)

3.1 索引一个文档 -- 保存一条记录 put和post都可以

## 索引(数据库):customer,类型(表名):external,编号为1
PUT customer/external/1
{
	"name": "Bob"
}

3.2 查询文档

## 索引/类型/id
GET customer/external/1

响应中有一个_seq_no字段,作用是乐观锁,并发控制,每次更新都会加1

PUT customer/external/1?if_seq_no=1&if_primary_term=1,两个人都想修改id为1的,当其中一个修改成功,_seq_no就会加1,此时另一个就不会修改成功了。

3.3 更新文档

## 会和原来的数据对比,如果一样,那么就不会改变,包括版本号、seq_no等都不会变
POST customer/external/1/_update
{
	"doc": {
		"name": "Andy"
	}
}

或者
## 每次都会更新数据,版本号等都会更新
POST/PUT customer/external/1
{
	"name":"Andy"
}

3.4 删除文档&索引(没有删除类型)

DELETE customer/external/1
DELETE customer

3.5 批量API

POST customer/external/_bulk
## 两行是一组
{"index": {"_id": 1}}
{"name": "David"}
{"index": {"_id": 2}}
{"name": "Jane"}

3.6 检索

GET bank/_search?q=*&sort=account_number:asc
或:
GET bank/_search
{
    "query": {
        "match_all": {}
    },
    "sort": [
        {
            "account_number": "asc"
        },
        {
            "balance": "desc"
        }
    ],
    "from": 0,
    "size": 5,
    "_source": ["字段1", "字段2"]
}

请求体就叫做queryDSL(领域对象语言)

3.6.1 match
{
    "query": {
        "match": {
            "account_number": 20
        }
    }
}

match去检索一个非字符串,那么相当于精确匹配,如果是字符串,相当于模糊查询。

{
    "query": {
        "match": {
            "address": "Kings"
        }
    }
}
在结果中会有_score,描述结果的分词匹配程度。
3.6.2 match_phrase

不对检索条件进行分词(区别于match,match会分词)

3.6.3 multi_match 多字段匹配
{
    "query": {
        "multi_match": {
            "query": "mill",
            "fields": ["address", "city"]
        }
    }
}
## address\city字段包含mill,都会匹配到

4. bool 查询 - 合并多个查询

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "gender": "F"    
                    }
                },
                {
                    "match": {
                        "address": "mill"
                    }
                }
            ],
            "must_not": [
                {
                    "match": {
                        "age": "38"
                    }
                }
            ],
            "should": [ ## 可以满足,不满足也没关系,影响的是_score
                {
                    "match": {
                        "lastname": "Wallace"
                    }
                }
            ]
        }
    }
}

4.1 filter过滤

filter和must should一样,但是不影响相关性得分。

5. term查询

term和match一样,精确到字段比如年龄等,用term查询,其他的字符串等需要全文检索的,用match查询

6. 聚合查询 aggregations

类比于Group By、sql的聚合函数等。比如搜索address中包含mill的所有人的年龄分布以及平均年龄,但是不需要这些人的详情:

GET bank/_search
{
    "query": {
        "match": {
            "address": "mill"
        }
    },
    "aggs": {
        "ageAgg": {
            "terms": {
                "field": "age",
                "size": 10  // group by age
            }
        },
        "aggAvg": {
            "avg": {
                "field": "age"  // avg(age)
            }
        }
    }
}