ElasticSearch学习笔记

ElasticSearch学习笔记

1. 基本配置

1.1 创建用户

ES不能在root用户下运行,所以我们首先需要创建用户用于运行ES服务:

adduser es

然后设置用户信息完成用户创建。

这里可以将用户加入 sudo 用户组,防止某些配置无法进行:

usermod -aG sudo es

然后切换到该用户进行以下操作,以防目录或文件的所有权导致某些操作无法进行:

su es

1.2 下载ES相关文件

在合适的目录下下载ES的压缩包并解压:

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.15.1-linux-x86_64.tar.gz

当然,考虑到服务器的网络问题,下载该文件可能需要比较长的时间,所以可以在本地下载好后上传到服务器上,速度会快很多。

然后解压该文件:

tar -xvf elasticsearch-8.15.1-linux-x86_64.tar.gz

进入解压后的文件目录,有如下目录或文件:

bin  config  jdk  lib  LICENSE.txt  logs  modules  NOTICE.txt  plugins  README.asciidoc

1.3 配置信息

进入用户主目录,设置用户级别环境变量:

vim .bash_profile

写入如下配置:

export ES_JAVA_HOME=/home/es/es/elasticsearch-8.15.1/jdk
export ES_HOME=/home/es/es/elasticsearch-8.15.1

保存并退出后执行如下命令使配置生效:

source .bash_profile

接下来进入ES安装目录,编辑配置文件:

vim config/elasticsearch.yml

具体内容如下:

# 配置节点对外提供服务的地址以及集群内通信地址
# 配置为 0.0.0.0 开启远程访问支持
network.host: 0.0.0.0

# 指定节点为单节点可以绕过引导检查
# 初学者建议设置为此开发模式
discovery.type: single-node

# 初学者建议关闭安全认证
xpack.security.enabled: false

1.4 启动ES并测试访问

进入ES的安装目录,在后台启动ES服务:

bin/elasticsearch -d

服务启动后,打开浏览器,访问服务器所在地址的 9200 端口,如果服务正常运行可以看到如下信息:

{
    "name": "iZ2ze5dxjax3b5pyet0agkZ",
    "cluster_name": "elasticsearch",
    "cluster_uuid": "qhrjVDuBQ-ChmEFI2pPrhQ",
    "version": {
        "number": "8.15.1",
        "build_flavor": "default",
        "build_type": "tar",
        "build_hash": "253e8544a65ad44581194068936f2a5d57c2c051",
        "build_date": "2024-09-02T22:04:47.310170297Z",
        "build_snapshot": false,
        "lucene_version": "9.11.1",
        "minimum_wire_compatibility_version": "7.17.0",
        "minimum_index_compatibility_version": "7.0.0"
    },
    "tagline": "You Know, for Search"
}

1.5 浏览器相关插件

可以在Chrome浏览器中安装一些插件以便于监控ES服务状态:

  • Multi Elasticsearch Heads

还有其他类似的监控插件,这里不再一一列举。

1.6 ES相关插件

对于中文搜索引擎,最重要的就是中文分词器插件,下面将介绍如何安装分词器插件。

首先是一些关于ES插件管理的命令:

# 查看已安装插件
bin/elasticsearch-plugin list
# 安装插件
bin/elasticsearch-plugin install plugin-name
# 移除插件
bin/elasticsearch-plugin remove plugin-name

然后安装中文分词插件:

bin/elasticsearch-plugin install analysis-icu

然后重启ES服务使插件生效。

可以在前面的浏览器插件中测试分词器的工作效果,发送 _analyzePOST 请求:

{
    "analyzer": "icu_analyzer",
    "text": "北京航空航天大学"
}

然后会得到如下的分词结果:

{
    "tokens": [
        {
            "token": "北京",
            "start_offset": 0,
            "end_offset": 2,
            "type": "<IDEOGRAPHIC>",
            "position": 0
        },
        {
            "token": "航空",
            "start_offset": 2,
            "end_offset": 4,
            "type": "<IDEOGRAPHIC>",
            "position": 1
        },
        {
            "token": "航天",
            "start_offset": 4,
            "end_offset": 6,
            "type": "<IDEOGRAPHIC>",
            "position": 2
        },
        {
            "token": "大学",
            "start_offset": 6,
            "end_offset": 8,
            "type": "<IDEOGRAPHIC>",
            "position": 3
        }
    ]
}

不过,这个分词的结果可能不能很好地满足需求,所以我们还需要安装另一个IK分词器open in new window,务必确保版本对应。

将下载好的分词器上传到服务器并解压到插件目录。

当前 plugins 目录下应该有两个插件:

analysis-icu  elasticsearch-analysis-ik-8.15.1

目录结构如下:

.
├── analysis-icu
│   ├── analysis-icu-8.15.1.jar
│   ├── icu4j-68.2.jar
│   ├── lucene-analysis-icu-9.11.1.jar
│   └── plugin-descriptor.properties
└── elasticsearch-analysis-ik-8.15.1
    ├── commons-codec-1.11.jar
    ├── commons-logging-1.2.jar
    ├── config
    │   ├── extra_main.dic
    │   ├── extra_single_word.dic
    │   ├── extra_single_word_full.dic
    │   ├── extra_single_word_low_freq.dic
    │   ├── extra_stopword.dic
    │   ├── IKAnalyzer.cfg.xml
    │   ├── main.dic
    │   ├── preposition.dic
    │   ├── quantifier.dic
    │   ├── stopword.dic
    │   ├── suffix.dic
    │   └── surname.dic
    ├── elasticsearch-analysis-ik-8.15.1.jar
    ├── httpclient-4.5.13.jar
    ├── httpcore-4.4.13.jar
    ├── ik-core-1.0.jar
    ├── plugin-descriptor.properties
    └── plugin-security.policy

重启ES服务使IK分词器插件生效。

然后我们再次使用浏览器测试IK分词器的分词效果:

ik_smart 会对文本做最粗粒度的拆分:

{
    "analyzer": "ik_smart",
    "text": "北京航空航天大学"
}

ik_max_word 会对文本做最细粒度的拆分:

{
    "analyzer": "ik_max_word",
    "text": "北京航空航天大学"
}

第一种配置的返回结果如下:

{
    "tokens": [
        {
            "token": "北京",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 0
        },
        {
            "token": "航空航天",
            "start_offset": 2,
            "end_offset": 6,
            "type": "CN_WORD",
            "position": 1
        },
        {
            "token": "大学",
            "start_offset": 6,
            "end_offset": 8,
            "type": "CN_WORD",
            "position": 2
        }
    ]
}

第二种配置的返回结果如下:

{
    "tokens": [
        {
            "token": "北京",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 0
        },
        {
            "token": "航空航天",
            "start_offset": 2,
            "end_offset": 6,
            "type": "CN_WORD",
            "position": 1
        },
        {
            "token": "航空",
            "start_offset": 2,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 2
        },
        {
            "token": "空航",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 3
        },
        {
            "token": "航天",
            "start_offset": 4,
            "end_offset": 6,
            "type": "CN_WORD",
            "position": 4
        },
        {
            "token": "天大",
            "start_offset": 5,
            "end_offset": 7,
            "type": "CN_WORD",
            "position": 5
        },
        {
            "token": "大学",
            "start_offset": 6,
            "end_offset": 8,
            "type": "CN_WORD",
            "position": 6
        }
    ]
}

2. 基本操作测试

ES的基本操作有创建索引、创建映射、插入文档、高亮查询、删除索引等,使用这些操作就可以搭建一个最基本的搜索引擎了。

可以使用postman发送一些请求来测试其工作效果。

2.1 创建索引

请求类型:PUT

请求地址:http://<elasticsearch_host>:<port>/<index_name>

可选请求体:

{
    "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 1
    }
}

执行请求:

PUT http://60.205.206.30:9200/index

无请求体,响应体为:

{
       "acknowledged": true,
       "shards_acknowledged": true,
       "index": "index"
}

2.2 创建映射

请求类型:POST

请求地址:http://<elasticsearch_host>:<port>/<index_name>/_mapping

请求体:

{
    "properties": {

    }
}

执行请求:

POST http://60.205.206.30:9200/index/_mapping

请求体:

{
       "properties": {
           "content": {
               "type": "text",
               "analyzer": "ik_max_word",
               "search_analyzer": "ik_smart"
           }
       }
}

响应体:

{
   "acknowledged": true
}

2.3 插入文档

请求类型:POST

请求地址:http://<elasticsearch_host>:<port>/<index_name>/_create/<id>

请求体:

{
    "content": "Content Content Content"
}

执行请求:

POST http://60.205.206.30:9200/index/_create/1

请求体:

{
       "content": "北京航空航天大学"
}

响应体:

{
       "_index": "index",
       "_id": "1",
       "_version": 1,
       "result": "created",
       "_shards": {
           "total": 2,
           "successful": 1,
           "failed": 0
       },
       "_seq_no": 0,
       "_primary_term": 1
}

执行请求:

POST http://60.205.206.30:9200/index/_create/2

请求体:

{
       "content": "北京理工大学"
}

响应体:

{
       "_index": "index",
       "_id": "2",
       "_version": 1,
       "result": "created",
       "_shards": {
           "total": 2,
           "successful": 1,
           "failed": 0
       },
       "_seq_no": 1,
       "_primary_term": 1
}

执行请求:

POST http://60.205.206.30:9200/index/_create/3

请求体:

{
       "content": "北京大学"
}

响应体:

{
       "_index": "index",
       "_id": "3",
       "_version": 1,
       "result": "created",
       "_shards": {
           "total": 2,
           "successful": 1,
           "failed": 0
       },
       "_seq_no": 2,
       "_primary_term": 1
}

2.4 高亮查询

请求类型:GET

请求地址:http://<elasticsearch_host>:<port>/<index_name>/_search

请求体:

{
    "query": {
        "match": {
            "content": "Query Content"
        }
    },
    "highlight": {
        "pre_tags": [
            "<tag1>",
            "<tag2>"
        ],
        "post_tags": [
            "</tag1>",
            "</tag2>"
        ],
        "fields": {
            "content": {
                
            }
        }
    }
}

在上面的例子中,我们已经插入了三条数据,接下来我们对其进行查询操作。

执行请求:

GET http://60.205.206.30:9200/index/_search

请求体:

{
       "query": {
           "match": {
               "content": "北航大学"
           }
       },
       "highlight": {
           "pre_tags": [
               "<tag1>",
               "<tag2>"
           ],
           "post_tags": [
               "</tag1>",
               "</tag2>"
           ],
           "fields": {
               "content": {

               }
           }
       }
}

响应体:

{
       "took": 12,
       "timed_out": false,
       "_shards": {
           "total": 1,
           "successful": 1,
           "skipped": 0,
           "failed": 0
       },
       "hits": {
           "total": {
               "value": 3,
               "relation": "eq"
           },
           "max_score": 0.1546153,
           "hits": [
               {
                   "_index": "index",
                   "_id": "3",
                   "_score": 0.1546153,
                   "_source": {
                       "content": "北京大学"
                   },
                   "highlight": {
                       "content": [
                           "北京<tag1>大学</tag1>"
                       ]
                   }
               },
               {
                   "_index": "index",
                   "_id": "1",
                   "_score": 0.12500812,
                   "_source": {
                       "content": "北京航空航天大学"
                   },
                   "highlight": {
                       "content": [
                           "北京航空航天<tag1>大学</tag1>"
                       ]
                   }
               },
               {
                   "_index": "index",
                   "_id": "2",
                   "_score": 0.12500812,
                   "_source": {
                       "content": "北京理工大学"
                   },
                   "highlight": {
                       "content": [
                           "北京理工<tag1>大学</tag1>"
                       ]
                   }
               }
           ]
       }
}

有意思的是,在这三条数据中,搜索北航大学,相关性最高的居然是北京大学!

2.5 删除索引

请求类型:DELETE

请求地址:http://<elasticsearch_host>:<port>/<index_name>

无请求体

为了保存测试结果,这里不再演示删除操作的结果。

3. 可视化客户端Kibana

Kibana是和ES协同工作的可视化客户端,首先在Download Kibana Free | Get Started Now | Elasticopen in new window下载合适版本的Kibana文件。

上传到服务器后解压文件:

tar -xvf kibana-8.15.1-linux-x86_64.tar.gz

解压文件后进入其安装目录,修改 config/kibana.yml 配置文件:

# 指定 Kibana 服务监听的端口号
server.port: 5601
# 指定 Kibana 服务绑定的主机地址
server.host: 0.0.0.0
# 指定 Kibana 连接到的 ES 实例的访问地址
elasticsearch.hosts: [
    "http://60.205.206.30:9200"
]
# 将 Kibana 的界面语言设置为中文
i18n.locale: "zh-CN"

然后后台启动服务:

nohup bin/kibana > logs/kibana.log 2>logs/error.log &

浏览器访问网站,打开左侧边栏中的开发工具,在控制台即可进行与上方postman相同的操作,具体可以查看教程。

4 了解ES核心概念

  • 了解搜索引擎的基础知识
    • 什么是全文检索
    • 什么是倒排索引
  • 了解ES常用术语
    • 什么是索引
    • 什么是映射
    • 什么是文档

4.1 什么是全文检索

全文检索是一种从大量文本中快速检索出包含指定词汇或短语的信息的技术。

4.2 什么是倒排索引

在一个文档集合中,每个文档都可视为一个短语的集合,倒排索引则是将词语映射到包含这个词语的文档的数据结构。

那么我们如何实现倒排索引呢?

  1. 文档预处理
  2. 构建索引
  3. 创建倒排列表
  4. 存储索引文件
  5. 查询处理

4.3 什么是索引?什么是映射?什么是文档?

ES中的索引就类似于MySQL中的表,也就是索引表;映射类似于MySQL中的Schema表结构;文档类似于MySQL表中的一行记录。

Last Updated 2024/10/1 22:55:53