ELASTIC SEARCH 搜索引擎
倒排索引
elastic search 使用倒排索引
- 文档:每条数据就是一个文档
- 词条:文档按照语义分成的词语
数据
id | title | price |
---|---|---|
1 | 小米手机 | 3399 |
2 | 华为手机 | 4399 |
3 | 华为充电器 | 49 |
4 | 小米手环 | 299 |
分词之后的索引
词条 | 文档id |
---|---|
小米 | 1,3,4 |
手机 | 1,2 |
华为 | 2,3 |
充电器 | 3 |
手环 | 4 |
查询是进行分词然后去匹配分词索引,能加快返回速度
es的数据格式
文档(doc)
elasticsearch是面向文档储存的,可以是数据中的一条商品数据,一个订单信息。
文档数据会被序列化为json格式后再储存到elastic中。
[
{
"id": "1",
"title": "华为手机",
"price": 100
},
{
"id": "2",
"title": "小米手机",
"price": 200
}
]
索引(index)
index可以看做数据中的表,主要是区分doc的类型
安装
elastic search
docker pull elasticsearch:7.17.19
docker network create es-learn
docker run -d --name es \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v es-data:/usr/share/elasticsearch/data \
-v es-plugins:/usr/share/elasticsearch/plugins \
--privileged --network es-learn \
-p 9200:9200 -p 9300:9300 \
elasticsearch:7.17.19
kibana
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-learn \
-p 5601:5601 kibana:7.17.19
分词器
es在创建倒排索引对文档分词时;在搜索时,需要对用户输入内容分词。但默认的分词规则对中文处理并不友好,我们在kibana的DevTool里测试:
//测试分词器
POST /_analyze
{
"analyze": "standard",
"text": "ES真的也太棒了"
}
es的默认分词会返回以下的结构:
{
"tokens": [
{
"token": "es",
"start_offset": 0,
"end_offset": 2,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "真",
"start_offset": 2,
"end_offset": 3,
"type": "<IDEOGRAPHIC>",
"position": 1
},
{
"token": "的",
"start_offset": 3,
"end_offset": 4,
"type": "<IDEOGRAPHIC>",
"position": 2
},
{
"token": "也",
"start_offset": 4,
"end_offset": 5,
"type": "<IDEOGRAPHIC>",
"position": 3
},
{
"token": "太",
"start_offset": 5,
"end_offset": 6,
"type": "<IDEOGRAPHIC>",
"position": 4
},
{
"token": "棒",
"start_offset": 6,
"end_offset": 7,
"type": "<IDEOGRAPHIC>",
"position": 5
},
{
"token": "了",
"start_offset": 7,
"end_offset": 8,
"type": "<IDEOGRAPHIC>",
"position": 6
}
]
}
由上可以看出默认分词对中文支持不好
一般情况下我们可以引用 ik 插件作为中文分词器
安装分词器
自动安装
使用 docker exec -it es /bin/bash
进入容器后
使用 in/elasticsearch-plugin install https://github.com/infinilabs/analysis-ik/releases/tag/{version}
安装好后重启docker容器
可以直接安装插件,但在国内会比较慢
手动安装
进入本地 volume
传入下载好的文件,从新启动es便可以完成安装
分词器类型
IK 分词器包含两种类型:
ik_smart
: 最少切分ik_max_word
: 最细切分
下面的返回可以更为之光的感受到两种的差距
ik_smart:
{
"tokens": [
{
"token": "es",
"start_offset": 0,
"end_offset": 2,
"type": "ENGLISH",
"position": 0
},
{
"token": "真的",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
},
{
"token": "也",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 2
},
{
"token": "太棒了",
"start_offset": 5,
"end_offset": 8,
"type": "CN_WORD",
"position": 3
}
]
}
ik_max_word:
{
"tokens": [
{
"token": "es",
"start_offset": 0,
"end_offset": 2,
"type": "ENGLISH",
"position": 0
},
{
"token": "真的",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
},
{
"token": "也",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 2
},
{
"token": "太棒了",
"start_offset": 5,
"end_offset": 8,
"type": "CN_WORD",
"position": 3
},
{
"token": "太棒",
"start_offset": 5,
"end_offset": 7,
"type": "CN_WORD",
"position": 4
},
{
"token": "了",
"start_offset": 7,
"end_offset": 8,
"type": "CN_CHAR",
"position": 5
}
]
}
ik分词器扩展和排除
要扩展ik分词器的词库,只需要修改一个ik分词器目录中的config目录中的ikAnalyzer.config.xml文件:
<properties>
<comment>ik Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展词典-->
<entry key="ext_dict">ext.dic</entry>
<!--用户可以在这里配置自己的排除词典-->
<entry key="ext_stopwords">stopword.dic</entry>
</properties>
索引操作
mapping属性
{
"age": 21,
"weight": 52.1,
"isMarried": false,
"info": "es学习",
"email": "hideyoshi@hideyoshi.top",
"score": [
99.1,
99.5,
98.9
],
"name": {
"firstName": "吉",
"lastName": "秀"
}
}
mapping是对索引库中的文档的约束,常见的mapping属性包括
type:字段数据类型,重建的类型有:
- 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
- 数值类型:long、integer、sort、byte、double、float
- 布尔:boolean
- 日期:date
- 对象:object
- index:是否创建索引,默认为true
- analyzer:使用哪种分词器
- properties:该字段的子字段
创建索引库
es通过restful请求操作索引库、文档。请求内容用dsl语句来表示。创建索引库和mapping的dsl语法如下:
PUT /索引库名称
{
"mappings": {
"properties": {
"字段名": {
"type": "text",
"analyzer": "ik_smart"
},
"字段名2": {
"type": "keyword",
"index": "false"
},
"字段名3": {
"type": "object",
"properties": {
"子字段": {
"type": "keyword"
}
}
}
}
}
}
查询和删除索引库
es通过restful请求操作索引库、文档
GET /索引库名称
DELETE /索引库名称
修改索引库只允许添加字段名称,不能修改已存在的字段名
PUT /索引库名称/_mapping
{
"properties": {
"新字段名": {
"type": "integer"
}
}
}
文档操作
es通过restful请求操作索引库、文档
GET /索引库名/_doc/文档id //新增
POST /索引库名/_doc/文档id //新建
PUT /索引库名/_doc/文档id //修改
DELETE /索引库名/_doc/文档id //删除
其中PUT
请求在id不存在时是新增、在id存在是为全量修改
局部修改为
POST /索引库名/_update/文档id
{
"doc":{
"字段名":"新的值“
}
}