1. 介绍
Elasticsearch 是一个非常强大的搜索引擎。它目前被广泛地使用于各个 IT 公司。Elasticsearch 是由 Elastic 公司创建。Elasticsearch 是一个分布式、免费和开放的搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。 Elasticsearch 基于 Apache Lucene 构建,并于 2010 年由 Elasticsearch N.V. 首次发布(现在称为 Elastic)。Elasticsearch 以其简单的 REST API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件,Elastic Stack 是一组用于数据摄取、丰富、存储、分析和可视化的免费开放工具。 通常被称为 ELK Stack。Elastic 公司也同时拥有 Logstash 及 Kibana 开源项目。这个三个项目组合在一起,就形成了 ELK 软件栈。他们三个共同形成了一个强大的生态圈。简单地说,Logstash 负责数据的采集,处理(丰富数据,数据转换等),Kibana 负责数据展示,分析,管理,监督,警报及方案。Elasticsearch 处于最核心的位置,它可以帮我们对数据进行存储,并快速地搜索及分析数据。随着后来的 Beats 加入,ELK 软件栈,也被称为 ELKB。
2. 安装
Elasticsearch自身带有JDK,如果要使用自己的Java版本,请设置ES_JAVA_HOME环境变量。如果必须使用与捆绑JVM不同的Java版本,最好使用受支持的LTS版本的Java的最新版本。Elasticsearch与某些openjdk特定的特性紧密耦合,因此它可能无法与其他jvm正常工作。
2.1 Windows
在windows环境下安装比较简单,只需要到ES官网下载压缩包解压,修改下elasticsearch.yml配置文件即可启动,在项目中通常采用Linux作为服务器操作系统,所以Windows只介绍单机安装。
2.1.1 下载
Elasitcsearch下载地址: https://www.elastic.co/cn/downloads/past-releases/elasticsearch-{下载的版本用-分割,如8-11-1}
选择Windows平台下载压缩包
解压完成后到config目录修改elasticsearch.yml
文件
2.2.2 修改配置
# 集群名称
cluster.name: es-cluster
# 节点名称
node.name: node-1
# 数据存放目录
path.data: E:\elastisearch\elasticsearch-7.6.2\data
# 日志存放目录
path.logs: E:\elastisearch\elasticsearch-7.6.2\logs
# 允许访问IP 0.0.0.0允许所有
network.host: 0.0.0.0
# ES访问端口
http.port: 9200
# 开启安全认证
xpack.security.enabled: true
# 启动模型,单机
discovery.type: single-node
修改JVM内存大小
## JVM configuration
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
# 其它配置内容不用动,只需要修改初始化堆内存和最大堆内存,最小只能设置成512M
-Xms1g
-Xmx1g
2.2.3 启动
在/bin目录下双击elasticsearch.bat,等待CMD控制台窗口启动完成,启动完成后在浏览器访问localhost:9200,启动过程中容控制台日志打印容易卡住,这样会导致localhost:9200访问不了,需要在控制台按回车,直到能够访问,如果等待许久后还是访问不了则需要检查日志打印中是否存在Error级别日志,需要根据Error日志打印内容进行排查启动失败原因。
需要账号密码是因为我们在配置文件中开启了安全认证,所以需要去初始化生成用户密码。
在/bin目录下进入cmd窗口
输入命令执行bat脚本
elasticsearch-setup-passwords interactive
根据控制台提示内容输入对应类型用户密码,有elastic
、kibana
、logstash_system
、apm_system
、beats_system
、remote_monitoring_user
这几个用户。
输入账密认证成功后就可以看到es的基本信息。
至此,windows环境下es就启动完成了。
2.2 Linux
2.2.1 单机
Elasticsearch是一个基于Lucene的搜索引擎,可以在linux系统环境中安装并运行。下面是Elasticsearch在linux系统环境中的安装步骤。
- 安装Java
Elasticsearch需要Java环境支持,因此需要先安装Java。可以在终端中输入以下命令安装:
sudo apt-get update
sudo apt-get install openjdk-8-jdk
- 下载和安装Elasticsearch
可以从官方网站https://www.elastic.co/downloads/elasticsearch 下载Elasticsearch压缩包,或者使用以下命令下载:
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.1-linux-x86_64.tar.gz
下载完成后,解压缩压缩包到指定目录中:
tar -zxvf elasticsearch-7.10.1-linux-x86_64.tar.gz
- 配置Elasticsearch
进入解压缩后的elasticsearch目录,修改config/elasticsearch.yml文件,设置集群名称、节点名称和监听地址等参数。例如:
cluster.name: my-cluster
node.name: my-node
network.host: 0.0.0.0
- 启动Elasticsearch
在elasticsearch的bin目录下,执行以下命令启动Elasticsearch:
./elasticsearch
- 验证Elasticsearch
使用curl命令验证Elasticsearch是否正常运行。例如:
curl -X GET "localhost:9200/"
若Elasticsearch正常运行,则会返回一些信息,如下:
{
"name": "my-node",
"cluster_name": "my-cluster",
"cluster_uuid": "H6XIdvpoT7OgXqIy8mqbUQ",
"version": {
"number": "7.10.1",
"build_flavor": "default",
"build_type": "tar",
"build_hash": "1c34507e66d7db1211f66f3513706fdf548736aa",
"build_date": "2020-12-05T01:00:33.671820Z",
"build_snapshot": false,
"lucene_version": "8.7.0",
"minimum_wire_compatibility_version": "6.8.0",
"minimum_index_compatibility_version": "6.0.0-beta1"
},
"tagline": "You Know, for Search"
}
至此,Elasticsearch在linux系统环境中安装成功。
2.2.2 集群
要在Linux下安装Elasticsearch集群,可以按照以下步骤进行:
- 安装Java环境
Elasticsearch是基于Java开发的,因此需要先安装Java环境。可以通过以下命令来检查是否已经安装了Java环境:
java -version
如果显示“command not found”等错误,则需要先安装Java环境。
- 下载Elasticsearch
可以从Elasticsearch官网下载最新版的Elasticsearch,也可以使用以下命令下载:
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.2-linux-x86_64.tar.gz
其中7.9.2表示Elasticsearch的版本号,可以根据实际需求进行修改。
- 解压和安装Elasticsearch
下载完成后,使用以下命令解压文件:
tar -zxvf elasticsearch-7.9.2-linux-x86_64.tar.gz
解压后,可以将Elasticsearch安装到任意目录,比如:
mv elasticsearch-7.9.2 /usr/local/elasticsearch
- 配置Elasticsearch集群
在配置Elasticsearch集群之前,需要先了解一些基本概念。
每个Elasticsearch节点都有一个唯一的节点名称,可以在配置文件中设置。在同一个集群中,所有节点的名称必须是唯一的。
每个Elasticsearch节点都有一个默认的HTTP端口9200和一个默认的节点间通信端口9300,如果需要修改这些端口,则需要在配置文件中设置。
每个Elasticsearch节点都有一个默认的数据目录和日志目录,如果需要修改这些目录,则需要在配置文件中设置。
在配置Elasticsearch集群之前,先在每个节点上创建一个配置文件,比如:
mkdir /usr/local/elasticsearch/config
vi /usr/local/elasticsearch/config/elasticsearch.yml
在配置文件中设置以下参数:
cluster.name: my-cluster
node.name: node-1
network.host: 192.168.1.101
http.port: 9200
transport.tcp.port: 9300
path.data: /usr/local/elasticsearch/data
path.logs: /usr/local/elasticsearch/logs
其中,cluster.name表示集群的名称,用于区分不同集群;node.name表示节点的名称,必须在同一集群中唯一;network.host表示节点的IP地址或域名;http.port表示节点的HTTP端口;transport.tcp.port表示节点间通信端口;path.data表示数据存储目录;path.logs表示日志存储目录。
以上配置只是示例,实际配置需要根据实际情况进行修改。
- 启动Elasticsearch集群
在每个节点上启动Elasticsearch集群:
cd /usr/local/elasticsearch/bin
./elasticsearch
启动后,可以通过以下命令检查集群状态:
curl http://localhost:9200/_cat/health?v
如果集群状态为green,则表示集群已经正常启动。
- 测试Elasticsearch集群
可以使用curl命令或者Elasticsearch客户端来测试集群的搜索、分析等功能。比如以下命令可以查询所有的索引:
curl -X GET "http://localhost:9200/_cat/indices?v"
如果集群正常,则会返回所有的索引信息。
至此,Elasticsearch集群安装完成。
3. 数据类型
Elasticsearch中支持很多数据类型,其中包括简单类型、复杂类型、坐标类型、特殊类型,下面只罗列一些常见的数据类型,更多数据类型需要到ES官网去看文档介绍。
文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/{这里填需要查看的ES版本号}/mapping-types.html
3.1 string
在string中包含keyword和text两个类型。
3.1.1 keyword
keyword类型的字段不会进行分词,如果字段内容是一个整体可以将字段设置为keyword类型,例如品牌、城市等信息。
3.1.2 text
当字段内容需要进行分词时可以将字段设置为text类型,例如产品名称、简介内容等。
3.2 Numeric
数值类型long, integer, short, byte, double, float, half_float, scaled_float,其中除了half_float和scaled_float这两种特殊类型外,其余类型和java中的没有什么区别。其中,half_float类型
3.3 Date
date类型用于日期数据的定义
3.4 Boolean
布尔类型,true或者false
3.5 Geo-point
地理坐标类型,用于存储地理坐标数据
3.6 Object
JSON格式的对象信息,在对象中也可以定义字段。
3.7 Arrays
在Elasticsearch中,数组不需要专用的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是数组中的所有值必须具有相同的数据类型。
例如:
- string数组:[“one”, “two”]
- integer数组:[1,2]
- object数组:[ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }]
4. 语法
在Elasticsearch中所有的操作API都是符合RestFul风格的,所以语法上很简单
Elasticsearch语法文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/{ES版本号}/query-dsl.html
4.1 索引库操作
4.1.1 索引库创建
创建一个酒店索引库,DSL在Kibana的dev tools中写的,因为这上面会有语法提示,在酒店索引库中有四个字段,brand、name、price、location,brand字段定义为keyword类型,品牌不需要分词,name字段定义为text,酒店名称需要进行分词,price字段定义为double,价格存在小数,location字段定义为地理坐标类型。
PUT /hotel
{
"mappings": {
"properties": {
"brand": {
"type": "keyword"
},
"name": {
"type": "text"
},
"price": {
"type": "double"
},
"location": {
"type": "geo_point"
}
}
}
}
4.1.2 查看索引库
GET <索引库名称>
GET /hotel
4.1.3 修改索引库
索引库一旦创建不可以修改,但是可以新增索引库字段。
PUT /<索引库名称>/_mapping
{
"properties":{
}
}
PUT /hotel/_mapping
{
"properties":{
"新字段名":{
"type":"integer"
}
}
}
4.1.4 删除索引库
DELETE <索引库名称>
DELETE /hotel
4.2 条件查询
4.3 经纬度查询
4.4 高亮显示
4.5 聚合查询
4.6 排序
4.7 分页
5. 自定义相关度算分
一般而言,Elasticsearch使用的是基于BM25模型的默认相关度算分。如果需要自定义相关度算分,可以通过设置自定义分数函数来实现。
- Function Score Query:
Function Score Query是Elasticsearch的一个查询类型,可以让用户自定义相关度算分公式来计算每个文档的得分。Function Score Query支持多种内置函数,例如gauss(高斯函数)、linear(线性函数)等等,也支持用户自定义函数。具体可以参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
以下是一个简单的例子:
{
"query": {
"function_score": {
"query": { "match_all": {} },
"functions": [
{
"script_score": {
"script": {
"lang": "painless",
"source": "double relevance = doc['relevance'].value; return relevance * _score;"
}
}
}
],
"boost_mode": "replace"
}
}
}
在上面的例子中,我们使用了一个自定义的分数函数,该函数使用文档中名为“relevance”的字段来计算分数。然后将这个分数乘以文档默认得分来得出最终得分。注意,这个例子中使用了Painless脚本来计算分数。
- Script Score Query:
Script Score Query也可以实现自定义相关度算分,通过设置一个计算得分的脚本来实现。该脚本可以使用Painless脚本语言进行编写,可以调用一些内置函数和API。具体可以参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-score-query.html
需要注意的是,自定义相关度算分可能会降低查询性能,因为需要计算每个文档的得分,而不是简单的TF-IDF算法。在使用自定义相关度算分之前,应该评估自己的需求和系统性能,选择合适的算法和查询方式。
6. 分词器
6.1 中文分词器
6.1.1 下载安装
中文分词器用的是IK分词器,下载地址:https://github.com/medcl/elasticsearch-analysis-ik/tags,需要下载和ES一样的版本。
下载好后解压放到ES安装目录下的/plugins目录下,重启ES。(Linux下操作亦是如此)
6.1.2 词库配置
在IK分词器目录下找到config目录下的IKAnalyzer.cfg.xml
配置文件,配置拓展词库、停用词库、远程拓展词库、远程停用词库,拓展词库的作用是在IK默认情况下有些词语识别不了,可以在拓展词库中进行拓展,停用词库是对某些词语不需要分词时进行停用,如介词,嗯、哦、啊这些。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
6.1.3 使用
在ik中文分词器中有两种模式,ik_smart
、ik_max_word
。ik_smart会做最粗粒度的拆分,适合 Phrase 查询,而ik_max_word会将文本做最细粒度的拆分,适合 Term Query。在创建字段时可以设置字段到索引库时的分词模式以及在对字段进行检索时的分词模式。
PUT /hotel/_mapping
{
"properties": {
"name": {
"type": "text",
"analyzer": "ik_smart", # 新增时采用ik_smart进行分词
"search_analyzer": "ik_max_word" # 检索时采用ik_max_word进行分词
}
}
}
采用ik_max_word模式切分
GET /_analyze
{
"text": "我是中国人",
"analyzer": "ik_max_word"
}
结果
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "是",
"start_offset" : 1,
"end_offset" : 2,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "中国人",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "中国",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "国人",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 4
}
]
}
采用ik_smart模式切分
GET /_analyze
{
"text": "我是中国人",
"analyzer": "ik_smart"
}
结果
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "是",
"start_offset" : 1,
"end_offset" : 2,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "中国人",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
}
]
}
6.2 拼音分词器
-
在Elasticsearch的安装目录下,进入plugins文件夹新建文件夹pinyin。
-
下载pinyin分词器插件。在Elasticsearch的官方网站上pull下来源码,也可以在github上下载。
-
解压缩下载的文件,将elasticsearch-analysis-pinyin文件夹中的所有文件复制到pinyin文件夹中。
-
重启Elasticsearch服务。
-
创建一个新的索引,并将分词器设置为pinyin。
PUT /test-index { "settings":{ "analysis":{ "analyzer":{ "my_pinyin":{ "tokenizer":"my_pinyin", "filter":[ "lowercase", "my_pinyin_filter"] } }, "tokenizer" : { "my_pinyin" : { "type" : "pinyin", "keep_original":true, "keep_first_letter":true, "keep_separate_first_letter":false, "keep_full_pinyin":false, "keep_joined_full_pinyin":true, "keep_none_chinese":false, "keep_none_chinese_in_joined_full_pinyin":true, "limit_first_letter_length": 16, "lowercase":true, "remove_duplicated_term":false } }, "filter": { "my_pinyin_filter": { "type": "pinyin", "keep_first_letter": false, "keep_separate_first_letter": false, "keep_full_pinyin": true, "keep_joined_full_pinyin": true, "keep_none_chinese": true, "keep_none_chinese_in_joined_full_pinyin": false, "keep_original": true, "limit_first_letter_length": 16, "lowercase": true, "remove_duplicated_term": false } } } } }
- 搜索测试。
GET /test-index/_search { "query" : { "match" : { "content" : "中华人民共和国" } } }
关于elasticsearch-analysis-pinyin的下载与使用,可以参考这里:https://github.com/medcl/elasticsearch-analysis-pinyin
6.3 自定义分词器
7. 补全提示
Elasticsearch提供了Completion Suggester来实现补全提示功能。
具体实现方式如下:
- 定义Mapping,使用“completion” type索引数据。
PUT /test
{
"mappings": {
"properties": {
"hotelName": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"suggest": {
"type": "completion",
"analyzer": "ik_max_word"
}
}
}
}
}
}
- 创建文档数据
PUT /test/_doc/1
{
"hotelName": "森林假日酒店"
}
- 通过suggest进行查询
GET /test/_search
{
"suggest": {
"my-suggest": {
"text": "森林", # 进行补全的关键字
"completion": {
"field": "hotelName.suggest" # 进行补全匹配的字段
}
}
}
}
- 响应结果
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"suggest" : {
"my-suggest" : [
{
"text" : "森林",
"offset" : 0,
"length" : 2,
"options" : [
{
"text" : "森林假日酒店",
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"hotelName" : "森林假日酒店"
}
}
]
}
]
}
}
在suggest下对应我们的搜索建议名下的options中就是符合条件的文档