一、ElasticSearch 简介
ElasticSearch 简称 ES ,是于Apache Lucene构建的开源搜索引擎,ES主要以轻量级JSON作为数据存储格式,同时也支持地理位置查询 。官方文档
适用场景有:
- 海量数据的关键字检索和存储,例如电商网站的关键词搜索商品信息
- 收集、存储和分析日志,指标和安全事件数据,比如ELK(ElasticSearch, Logstash, Kibana)
- 做为地理信息系统(GIS) 管理,集成和分析空间信息
二、 文档和索引
Elasticsearch是一个分布式文档存储。存储已序列化为JSON文档的复杂数据结构。当集群中有多个Elasticsearch节点时,存储的文档将分布在集群中,并且可以从任何节点立即访问存储文档时,将在1秒内几乎实时地对其进行索引和完全搜索。Elasticsearch使用称为倒排索引的数据结构,该结构支持非常快速的全文本搜索。
1、索引(index)
索引类似于关系型数据库中Database 的概念, 比如电商系统中,按微服务的方式划分,可以分为商品索引、订单索引、会员索引等等,类似于关系数据库中的 商品库, 订单库和会员库,但索引命名必须全部用小写字母。
索引是映射类型的容器, elasticsearch中的索引是一个非常大的文档集合。索|存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。
2、类型(type)
在一个索引中可以有多个类型, 类似关系数据库中的表, 比如订单索引中可以有订单主类型、订单明细类型、订单评价类型等。
在5.x版本以前可以在一个索引中定义多个类型,6.x之后版本也可以使用,但是不推荐,在7~8.x版本中彻底移除一个索引中创建多个类型
3、映射(mapping)
它类似于传统关系型数据中table的schema,用于定义一个索引(index)中的类型(type)的数据的结构。 在ES中,我们可以手动创建type(相当于table)和mapping(相关与schema),也可以采用默认创建方式。在默认配置下,ES可以根据插入的数据自动地创建type及其mapping。 mapping中主要包括字段名、字段数据类型和字段索引类型
4、文档
类似关系表中的一条数据,在这里是指type 中的一条记录或一个json 传,文档采用的是json 方式存储,类似mongoDB 数据库。
三、ES 基本操作
IK提供了两个分词算法: ik_ smart和ik_ max_ word ,其中ik_ smart为最少切分, ik_ max_ _word为最细粒度划分!
GET _analyze
{
"analyzer": "ik_smart",
"text": "我是社会主义接班人"
}
GET _analyze
{
"analyzer": "ik_max_word",
"text": "我是社会主义接班人"
}
以下操作,可以推荐在kibana 上进行。
1、索引(index)操作
# 创建索引
PUT /world/
# 查看索引
GET /_cat/indices?v
# 删除指定索引
DELETE /world
一般添加文档(document)数据时,会自动创建索引,在api 引用时,会根据model 类型自动创建类型(type)
2、类型(type)操作
# 在 world索引下创建 person 类型
PUT /world
{
"mappings": {
"person":{
"properties":{
"id": {"type": "integer"},
"name" : {"type": "text"},
"age" : {"type":"integer"},
"birth" : {"type":"date"}
}
}
}
}
# 查看类型
GET /world/_mapping/person
3、文档(document) 基本操作
# 添加文档 /索引/类型/id 多次执行,新的数据覆盖老的
PUT /world/person/1
{
"id":1,
"name":"panlei2",
"age":31,
"birth":"1991-09-02"
}
# 查询文档
GET /world/person/1
# 删除文档
DELETE /world/person/1
# 更新文档
# 1、更新原有数据
POST /world/person/1/_update
{
"doc":{
"age":29
}
}
# 添加新数据
POST /world/person/1/_update
{
"doc": {
"name":"lei",
"nickname":"leilei",
"nickLike":"ll"
}
}
# 在原有数据上更新
POST /world/person/1/_update
{
"script": "ctx._source.age+=5"
}
批量操作:
# 1、 批量索引两个文档
PUT /world/person/_bulk
{"index":{"_id":2}}
{"name":"yy","age":25,"birth":"2020-09-07"}
{"index":{"_id":3}}
{"name":"hc","age":2,"birth":"2020-09-01"}
# 2、更新文档同时删除文档
POST /world/person/_bulk
{"update":{"_id":"1"}}
{"doc":{"name":"PL"}}
{"delete":{"_id":2}}
{"index":{"_id":3}}
{"age":12}
四、高级检索 Start Searching
ES官方提供了两中检索方式:一种是通过 URL 参数进行搜索,另一种是通过 DSL(Domain Specified Language) 进行搜索。官方更推荐使用第二种方式,第二种方式是基于传递JSON作为请求体(request body)格式与ES进行交互,这种方式更强大,更简洁。
1、URL 参数查询: GET /world/person/_search?参数
# q:查询 sort:排序 size:每页返回条数 from:第几页开始(0) _source:展示哪几个字段
GET /ems/emp/_search?q=*&sort=age:desc&size=10&from=0&_source=name,age
2、DSL查询: GET /index/type/_search {请求体}
# 1、查询所有
GET /world/person/_search
{
"query": {
"match_all": {}
}
}
# 2、查询所有并排序
GET /world/person/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
#3、分页查询
GET /world/person/_search
{
"query": {
"match_all": {}
},
"size": 10,
"from": 0,
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
# 4、指定查询结果返回指定字段
GET /world/person/_search
{
"query": {
"match_all": {}
},\
"_source": ["name","age"]
}
# 5、 term查询,基于关键词查询
GET /world/person/_search
{
"query": {
"term": {
"content": {
"value": "spring"
}
}
}
}
# 6、分析分词
GET /_analyze
{
"text": "hello world"
}
1、text 类型是分词的,ES 默认使用标准分词器,标准分词是按字分词,英语是按单词分词
2、在ES 中,只有text 会分词,其他类型不分词
ES 索引库原理:
# 范围查询
GET /ems/emp/_search
{
"query": {
"range": {
"age": {
"gte": 0,
"lte": 20
}
}
}
}
# 关键词前缀查询
GET /ems/emp/_search
{
"query": {
"prefix": {
"name": {
"value": "小"
}
}
}
}
# 通配符查询 *通配所有 ?匹配一个
GET /ems/emp/_search
{
"query": {
"wildcard": {
"address": {
"value": "北*"
}
}
}
}
# 多id 查询
GET /ems/emp/_search
{
"query": {
"ids": {
"values": ["gQAvaXQBqXUotQFEybN-","jwAvaXQBqXUotQFEzbPe"]
}
}
}
# fuzzy 模糊查询 最大模糊错误 必须在0-2之间
GET /ems/emp/_search
{
"query": {
"fuzzy": {
"content": "Sprong"
}
}
}
# 布尔查询 must shoud must_not
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"age": {
"value": "23"
}
}
},
{
"term": {
"address": {
"value": "北京"
}
}
}
]
}
}
}
# 高亮查询 对查询结果做渲染
GET /ems/emp/_search
{
"query": {
"term": {
"content": {
"value": "redis"
}
}
},
"highlight": {
"fields": {
"*":{}
},
"pre_tags": ["<span style='color:red'>"],
"post_tags": ["</span>"]
}
}
五、安装IK 分词器
在线安装:
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.0/elasticsearch-analysis-ik-6.3.0.zip
离线安装:
1、在git 仓库找到版本对应的tag,下载到服务器
2、解压到 plugin/ik 目录下,直接启动es 就可以(es中如果有数据,就先删除数据)
测试IK 分词是否安装成功
GET /_analyze
{
"text": "中华人民共和国国歌",
"analyzer": "ik_max_word"
}
ik_max_word: 会将文本做最细粒度的拆分`,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”
ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。
当使用Ik 分词器时,需要重新指定分词器
PUT /world
{
"mappings": {
"person":{
"properties":{
"id": {"type": "integer"},
"content" : {"type": "text","analyzer": "ik_max_word"},
"age" : {"type":"integer"},
"birth" : {"type":"date"}
}
}
}
}
这时候可以用关键词查询一下:
GET /world/person/_search
{
"query": {
"term": {
"content": {
"value": "框架"
}
}
}
}
如果想修改分词器的词典,修改文件
elasticsearch-6.8.12/plugins/ik/config/IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords">custom/ext_stopword.dic</entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">location</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>
</properties>
六、过滤查询
语法:
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"match_all": {}}
],
"filter": {
"range": {
"age": {
"gte": 10
}
}
}
}
}
}
1、在执行filter和query时,先执行filter在执行query
2、Elasticsearch会自动缓存经常使用的过滤器,以加快性能。
常见的过滤器类型
GET /ems/emp/_search # 使用term过滤
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "小黑"
}
}}
],
"filter": {
"term": {
"content":"框架"
}
}
}
}
}
GET /dangdang/book/_search #使用terms过滤
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"terms": {
"content":[
"科技",
"声音"
]
}
}
}
}
}
ranage filter:
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"range": {
"age": {
"gte": 7,
"lte": 20
}
}
}
}
}
}
exists filter
过滤存在指定字段,获取字段不为空的索引记录使用
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"exists": {
"field":"aaa"
}
}
}
}
}
ids filter
过滤含有指定字段的索引记录
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"ids": {
"values": ["1","2","3"]
}
}
}
}
}