ES搜索
elastic search
一套搜索引擎技术,主要技术栈包括
-
Elasticsearch:用于数据存储、计算和搜索
-
Kibana:用于数据可视化
在数据库模糊查询中,因为不走索引,所以效率很低,而在搜索引擎中,不仅效率高,而且即使出现个别错字,或者用拼音搜索,甚至用同义词搜索都能正确匹配数据
ES的docker安装(默认端口9200)
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 hm-net \
-p 9200:9200 \
-p 9300:9300 \
elasticsearch:7.12.1
Kibana的docker安装(默认端口5601)
es的可视化控制台
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=hm-net \
-p 5601:5601 \
kibana:7.12.1
倒排索引
先了解两个概念
文档(document):即数据库中的行,每个文档代表一条数据
词条(term):对数据分词得到的词就是词条
创建倒排索引:
将每一个文档的数据利用分词算法做拆分,得到多个词条
创建表,表中每行数据包含词条,词条所在的文档id,位置等信息
因为词条是唯一的,所以词条可以作为数据库的索引
根据倒排索引做查询:
先对搜索条件进行分词得到词条
根据词条进行查询,得到文档id
最终结果集就是这些文档id对应的文档
词条和文档id都是对应表中的索引,查询效率很高
ES概念
文档:ES所面向存储的数据,会被序列化为json数据在es中存储
{
"id": 1,
"title": "小米手机",
"price": 3499
}
{
"id": 2,
"title": "华为手机",
"price": 4999
}
{
"id": 3,
"title": "华为小米充电器",
"price": 49
}
{
"id": 4,
"title": "小米手环",
"price": 299
}
索引:将类型相同的文档集中在一起管理,称为索引(index),类似数据库中的表
映射:类似数据库中表的字段约束,用以定义表的结构和字段的名称和类型等信息
字段:即每个索引中的文档的字段(属性),和数据库中的字段(列)一致
MySQL和ES
一般在安全性要求较高的操作中使用mysql实现
在查询性能要求较高的搜索中,使用ES实现
再通过例如canal+mq的方式实现数据同步,保证一致性
IK分词器
一个高效,精准的中文分词算法分词器
docker安装
docker exec -it es ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip
分词模式
包含两种模式
ik_smart:智能语义切分(粗粒度)
ik_max_word:最细粒度切分(细粒度)
可以通过在配置文件IkAnalyzer.cfg.xml中添加扩展词典实现自定义分词
ES索引库操作
Mapping映射属性
Mapping是对索引库中文档的约束,常见的Mapping属性包括:
type
:字段数据类型,常见的简单类型有:- 字符串:
text
(可分词的文本)、keyword
(精确值,例如:品牌、国家、ip地址) - 数值:
long
、integer
、short
、byte
、double
、float
、 - 布尔:
boolean
- 日期:
date
- 对象:
object
- 字符串:
index
:是否创建索引,默认为true
analyzer
:使用哪种分词器properties
:该字段的子字段
索引库的操作
采用Restful风格的API,请求参数采用json风格
创建索引库和映射
- 请求方式:
PUT
- 请求路径:
/索引库名
,可以自定义 - 请求参数:
mapping
映射
PUT /索引库名称
{
"mappings": {
"properties": {
"字段名":{
"type": "text",
"analyzer": "ik_smart"
},
"字段名2":{
"type": "keyword",
"index": "false"
},
"字段名3":{
"properties": {
"子字段": {
"type": "keyword"
}
}
},
// ...略
}
}
}
查询索引库
- 请求方式:GET
- 请求路径:/索引库名
- 请求参数:无
GET /索引库名
修改索引库
索引库不能修改映射,因为一旦修改映射就会影响倒排索引
但是可以添加新字段到索引库中
PUT /索引库名/_mapping
{
"properties": {
"新字段名":{
"type": "integer"
}
}
}
删除索引库
- 请求方式:DELETE
- 请求路径:/索引库名
- 请求参数:无
DELETE /索引库名
文档操作
新增文档
post /索引库名/_doc/文档id
POST /索引库名/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
"字段3": {
"子属性1": "值3",
"子属性2": "值4"
},
}
查询文档
get /索引库名称/_doc/条件
GET /{索引库名称}/_doc/{id}
删除文档
delete /索引库名/_doc/文档id
DELETE /{索引库名}/_doc/id值
修改文档
分为全量修改和局部修改
全量修改:覆盖原来的文档(删除原来的文档)
局部修改:修改文档中的部分字段
全量修改
put /索引库名/_doc/文档id
PUT /{索引库名}/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
// ... 略
}
局部修改
post /索引库名/_update/文档id
POST /{索引库名}/_update/文档id
{
"doc": {
"字段名": "新的值",
}
}
批处理
POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }//新增文档
{ "field1" : "value1" }//新增文档内容
{ "delete" : { "_index" : "test", "_id" : "2" } }//删除文档
{ "create" : { "_index" : "test", "_id" : "3" } }//创建文档
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }//更新文档
{ "doc" : {"field2" : "value2"} }