ES笔记:基础概念和使用
ES全称ElasticSearch,是一个开源的高扩展的实时的分布式全文检索和分析引擎,主要用于全文检索、结构化搜索、分析,扩展性非常好,可以扩展到上百台服务器,处理PB级别(1PB=1024TB)的数据。使用的编程语言为Java,以Lucene为核心,以RESTful API风格来实现索引和搜索的功能,让全文搜索变得更加简单。
注: 此笔记使用的ES版本为7.6.1
API文档: API conventions | Elasticsearch Guide [8.5] | Elastic
1 下载安装
1.1 ES下载安装
下载地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch
Windows安装: windows版本下载下来后解压即可使用。配置文件在 config/elasticsearch.yml
,默认端口为9200,ES启动路径为 bin/elasticsearch.bat
(直接在dos窗口运行该文件即可(或直接鼠标双击也行)),启动后浏览器访问 http://localhost:9200/
,出现经典的“You Know, for Search”则表示启动成功。
1.2 Kibana下载安装
Kibana是一个专门用于ElasticSearch的开源分析和可视化平台,可以用来搜索和查看ES中的数据,使用的时候注意需要 下载与ES一致的版本 。
下载地址: https://www.elastic.co/cn/downloads/kibana
Windows安装: Kibana也是解压即用的包,不过运行之前需要把依赖包装一下。在dos窗口cd到解压目录,执行 cnpm intall
安装依赖包即可(cnpm可以直接百度怎么安装和配置),然后直接运行 bin/kibana.bat
就可以了。注意运行Kibana的时候需要保证ES已经启动运行好了,否则Kibana无法顺利启动。最后按照提示访问默认的端口即可 http://localhost:5601/
。
Kibana中文配置: Kibana默认的语言是英文,可以通过修改配置将其设置为中文,支持的中文配置文件在安装目录下的 x-pack\plugins\translations\translations\zh-CN.json
,配置时在安装目录的 config/kibana.yml
文件中修改 i18n.locale: "en"
为 i18n.locale: "zh-CN"
(英文的配置默认是注释掉的,所以只需要将中文的配置直接添加进去即可),配置修改后,重启Kibana即可。
2 基础概念
2.1 集群
ES是按照集群进行设计的,即便我们只安装了一个节点(服务器),也是按集群来运行的,这个默认的集群名称就是elasticsearch。
2.2 索引和文档
索引(index)是面向文档(document)的,一个索引中可以有多个文档,文档是ES中“一条数据”的最小表示单位。与关系数据库作类比,一个文档相当于关系数据库中的一条数据(记录)或一个实例对象,关系数据库中表的字段或对象的属性在ES中使用field来描述,而一个field则使用key-value键值对来存储。
ES中最大的特色就是一切皆json,由此一个文档中可以非常方便的增加或删除一个字段(field),而不用担心破坏或影响这条数据(文档)。
2.3 分片
ES后台会默认将索引进行分片,并将这些“片”分散存储在集群中不同的节点上。
2.5 分词
将一段中文、英文或别的语言划分成一个一个的关键字,如“倒排索引”可以分为“倒排”、“索引”、“倒”、“排”等词,中文默认按字进行拆分,英文则默认按单词拆分。我们在使用百度、Google等搜索引擎进行搜索的时候,就是先将输入的内容进行分词(关键字),再按分词结果去数据库中进行搜索。
2.5 倒排索引
ES特色之一就是使用了倒排索引来更好地支持全文搜索。倒排索引的基础原理就是将文档进行分词(分词是指将文档按词拆分,如“倒排索引”可以分为“倒排”、“索引”、“倒”、“排”等词,英文则通常按单词划分),然后记录分词对应的文档,当用户搜索某个关键词时,ES会使用分词为每个文档“计分”(score),文档中该关键词出现的越多,得分就会越高,反之则越低,而文档分数越高,则它出现在搜索结果中的权重就会越大。
3 基础使用
ES中对于数据操作,包括创建索引、文档,查询文档数据等都是通过REST请求的方式,具体的ES使用方式和语法会在请求的URL和请求体中体现。
3.1 基础REST操作
Method | URL | 说明 |
---|---|---|
PUT | /索引名 | 创建索引 |
POST | /索引名/_doc/文档id | 创建指定id的文档 |
POST | /索引名/_create/文档id | 创建指定id的文档 |
POST | /索引名/_doc | 创建随机id的文档 |
POST | /索引名/_update/文档id | 更新指定id的文档 |
DELETE | /索引名/_doc/文档id | 删除指定文档 |
GET | /索引名/_doc/文档id | 查询指定文档 |
POST | /索引名/_doc/_search | 查询该索引的所有文档 |
3.2 基本数据类型
字符串: text(可以进行分词)、keyword(作为一个整体“单词”,不可被继续分词)。
数值: long、integer、short、byte、double、float、half_float、scaled_float。
日期: date。
布尔值: boolean。
二进制: binary。
示例: 创建一个索引并为每个字段指定数据类型,此时并未创建任何文档数据。(以下示例中可以使用 PUT /index2/_mapping
对已创建的映射关系进行修改,此时请求体第一层的key就直接是properties了)
# 请求url:PUT /index2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "long"
},
"birthday": {
"type": "date"
}
}
}
}
3.3 常用内置REST操作
查看ES健康状况
GET _cat/health
查询结果如 1683566272 17:17:52 elasticsearch yellow 1 1 5 5 0 0 2 0 - 71.4%
。
查看所有索引基本情况
GET _cat/indices
查询结果如 yellow open index1 fqDrMEiuSW6SKsBXgzXf8Q 1 1 1 0 3.7kb 3.7kb
。
查看ES集群节点信息
GET _cat/nodes
查看ES集群信息
GET /_cluster/health
3.4 简单查询
如果只是简单的查询,可以在url中直接使用查询参数q指定查询条件。
示例: GET /index1/_search?q=name:zhangsan
查询url中不用带上type类型值,使用_search表示搜索,q表示url中的查询参数key,name指要查询的字段名称,冒号后面就是要匹配的值(如果字段类型是keyword,那么就只能整词匹配,相当于精确匹配)。查询结果如下(查询结果中的score表示结果的匹配度,匹配度越高,则score的值越高):
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "index1",
"_type" : "type1",
"_id" : "1",
"_score" : 0.2876821,
"_source" : {
"name" : "zhangsan",
"age" : 18
}
}
]
}
}
3.5 复杂查询
3.5.1 query查询
复杂的查询可以在请求体中使用query参数指定条件。如:
GET /index1/_search
{
"query": {
"match": {
"name": "zhangsan"
}
}
}
同一个字段如果想要多条件查询,达到类似
name in ('zhangsan, 'lisi')
的效果,则可以使用空格将条件分开,如"name": "zhangsan lisi"
。
常用匹配条件:
- match:分词匹配,需要指定匹配的字段及其值,需要注意的是此处“词”的概念,是指分词器分完词之后的词。
- match_phrase:全词(精确)匹配,会将key-value中的value作为一个整体去进行匹配。
- match_all:查询全量数据,对应json体可以不用传值,使用一个空的{}即可。
查询结果示例及其字段解释:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : { # hits即查询结果,这个json中保存的是结果相关的数据
"total" : { # 查询到的总量描述
"value" : 1, # 查询结果条数
"relation" : "eq" # 查询的方式
},
"max_score" : 0.9808291, # 查询结果中最大的score
"hits" : [ # 查询到的结果列表,即文档列表,一个json表示一个文档
{
"_index" : "index1",
"_type" : "type1",
"_id" : "1",
"_score" : 0.9808291, # 此条数据的匹配score值
"_source" : { # 文档中其他自定义的属性值
"name" : "zhangsan",
"age" : 18
}
}
]
}
}
3.5.2 _source过滤
_source参数用于对查询结果过滤,指定查询结果需要返回的字段,不指定则默认返回文档中的全部字段。
GET /index1/_search
{
"query": {
"match": {
"name": "zhangsan"
}
},
"_source": ["name"] # 指定返回结果的_source字段
}
3.5.3 sort排序
使用sort参数可以对查询结果进行排序。
GET /index1/_search
{
"sort": {
"age": { # 根据age字段进行升序排序
"order": "asc"
}
}
}
3.5.4 from/size分页查询
from/size参数用于指定对结果进行分页,表示起始编号(从0开始)和每页的数据条数。
GET /index1/_search
{
"sort": {
"age": {
"order": "asc"
}
},
"from": 0,
"size": 1
}
3.5.5 must/should/must_not查询
在ES中想要达到SQL中and/or/not的效果,可以使用bool参数,在其json中进一步指定must参数(相当于and)、should参数(相当于or)、must_not参数(相当于not)。
GET /index1/_search
{
"query": {
"bool": { # 同时指定name和age作为查询条件
"must": [ # must表示列表中的查询条件都需要满足
{
"match": {
"name": "zhangsan"
}
},
{
"match": {
"age": 18
}
}
]
}
}
}
3.5.6 filter过滤器
filter过滤器也是在bool参数中使用,range表示范围过滤, gte表示大于等于(大于则是 gt), lte表示小于等于(小于则是le)。
GET /index1/_search
{
"query": {
"bool": {
"filter": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
}
}
3.5.7 term精确匹配
term参数精确匹配,会根据类型为keyword的字段进行全词匹配,当字段类型为text时,还是会使用分词器进行模糊匹配。该参数与match参数不同的是,使用空格时会将空格视为一个整体的查询条件,不会进行多条件查询。
GET /index1/_search
{
"query": {
"term": {
"name": "zhangsan"
}
}
}
3.5.8 highlight高亮
该参数在会查询结果中将匹配成功的词添加 <em></em>
标签,如果想要自定义高亮标签,可以使用 pre_tags
和 post_tags
指定。
GET /index1/_search
{
"query": {
"term": {
"name": "zhangsan"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
查询结果示例:
{
"took" : 196,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.9808291,
"hits" : [
{
"_index" : "index1",
"_type" : "type1",
"_id" : "1",
"_score" : 0.9808291,
"_source" : {
"name" : "zhangsan",
"age" : 18
},
"highlight" : {
"name" : [
"<em>zhangsan</em>"
]
}
}
]
}
}
自定义高亮标签及其查询结果示例:
GET /index1/_search
{
"query": {
"term": {
"name": "zhangsan"
}
},
"highlight": {
"pre_tags": "<p class='key' style='color:red'>",
"post_tags": "</p>",
"fields": {
"name": {}
}
}
}
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.9808291,
"hits" : [
{
"_index" : "index1",
"_type" : "type1",
"_id" : "1",
"_score" : 0.9808291,
"_source" : {
"name" : "zhangsan",
"age" : 18
},
"highlight" : {
"name" : [
"<p class='key' style='color:red'>zhangsan</p>"
]
}
}
]
}
}
3.5.9 aggs聚合查询
可以使用aggs进行计数、平均值计算等聚合查询,由于查询时会将原始数据一并返回,当你不想要原始数据时,可以使用 "size": 0
参数(和aggs参数同级)过滤掉原始数据。
GET /index1/_search
{
"aggs": { # 聚合查询
"age_group": { # 查询结果命名,可以自定义
"terms": { # 聚合方式:terms表示按项进行统计(个数),相当于SQL中的group by。
"field": "age" # 需要聚合的字段
}
}
}
}
查询结果:
{
"took": 31,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "index1",
"_type": "type1",
"_id": "2",
"_score": 1.0,
"_source": {
"name": "lisi",
"age": 19
}
},
{
"_index": "index1",
"_type": "type1",
"_id": "3",
"_score": 1.0,
"_source": {
"name": "wangwu",
"age": 20
}
},
{
"_index": "index1",
"_type": "type1",
"_id": "1",
"_score": 1.0,
"_source": {
"age": 17,
"name": "zhangsan"
}
}
]
},
"aggregations": {
"age_group": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 17,
"doc_count": 1
},
{
"key": 19,
"doc_count": 1
},
{
"key": 20,
"doc_count": 1
}
]
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY