type
status
date
slug
summary
tags
category
password

1、索引介绍

1.1 索引是什么

Elasticsearch 的索引(Index)是 Elasticsearch 中存储、组织和搜索文档的逻辑容器,一个索引通常包含一组具有相似特征的文档(Document)。一个索引可以视作关系数据库中的一张表。
Elasticearch 7.0 以后版本新建一个索引的语法如下:
索引结构主要包含settingsmappings两部分。
  • settings:定义 index 分片数量、副本数量、解析器等相关的配置信息。上面定义 3 个主分片(主分片在设定后不能修改),每个主分片有 1 个分片副本(分片副本可以在运行过程中根据业务需要动态调整)。
  • mappings:定义 document 及其包含的字段类型和索引方式相关的信息。上面定义了 name、age、address 三个字段,其中 name 和 address 的字段类型为 text,age 的字段类型为 integer。

1.2 索引分片(Shard)机制

分片(shard)是 Elasticsearch 中存储数据的最小单元。一个索引被分成多个分片,分散到多台服务器上,每个分片存储一部分数据。分片分为 shardreplica
  • shard:只有一个,为了解决数据在单一节点存储的问题而做的水平扩展,将数据分片后存放在不同的节点上可以提高对于数据操作的吞吐量及可扩展性。此参数一旦在索引(Index)创建完成后,则不可以进行修改。
  • replica:是对 shard 的备份,为了解决数据可用性问题,通常在分片数据丢失后,如果有副本数据在的话可以保证数据的完整性。并且在高吞吐量场景时,增加副本数量可以提供服务的读取吞吐量。此参数可以在索引创建时指定,也可以在创建后进行调整。replica 值越大搜索效率越高,但写入性能越低(一条数据写入操作需要做 1 + replicas 遍),具体值与集群 data 节点数量相关,不宜超过(data 节点数 - 1)
比如有一个索引,shard 设置为 5,replica 设置为 1,那么总的切片数为:shard(5) + shard(5) * replicas(1) = total(10)。
每次修改的时候都会先直接修改主分片 shard,再同步其他所有副本分片 replica。查询的时候则在 shard 和 replica 中随机选择一个。

1.2.1 分片的分配机制

当我们定义好主分片和副本分片的数量之后,集群的主节点将索引的各个分片分配到集群的各个节点上,这个过程就叫分片的分配。可以使用下面的请求查看索引 my-index 的各个分片的分配状态。
返回结果如下:
在返回的结果中,可以看到主分片被成功分配在节点 node-2 上,副本分片被分配在节点 node-1 上。
索引分片分配的几个原则:
  • 当集群的节点数目发生变化、索引的副本分片数目发生变化时,也会触发分片的分配。在这个过程中,需要把节点现有的分片移动到其他的节点上。如果在同一时刻需要移动的分片数太多且分片容量较大,则这个过程会比较耗时。
  • 主节点为每个节点分配索引分片的时候,默认情况下,它会尽可能把同一个索引的分片分配到更多的节点上,这样在读写索引数据的时候就可以利用更多的硬件资源,可提升读写的效率。
  • 在分配分片的过程中,永远不可以把同一个索引的某个主分片和它的副本分片分配到同一个节点上,也不可以把某个主分片的多个副本分片分配到同一个节点上。否则,一旦该节点“挂掉”整个集群就可能会丢失数据。因此,如果一个索引的副本分片数较多而集群节点数较少,则可能会导致某些副本分片没有得到分配而不起作用。
  • 对于一个总分片数为 N 的索引而言,当集群节点的数目达到 N 以后,由于没有多余的分片可以分配到新的节点上,继续添加新节点无法再提升该索引的读写性能。

1.2.2 索引分片的路由规则

当主分片分配完毕之后,我们写入一条数据的时候,这条数据会被路由到其中一个主分片进行保存。那么如何决定数据应该被保存到哪个分片上的呢?默认情况下,Elasticsearch 会使用以下公式来决定数据被写入的分片的编号。
routing 默认是文档的 _id 。routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。
💡
如果允许主分片数量发生改变,就意味着所有的数据需要重新路由,因此 Elassticsearch 禁止在索引建立以后修改主分片的数量。
虽然手动指定路由值可以减少查询使用的分片数,但是这有可能引发大量的数据被路由到少数几个分片,而其余的很多分片数据量太少,使得分片的大小不均匀。Elasticsearch 为了缓解这个问题,提供了索引分区的配置,允许使用同一路由的数据被分发到多个分片而不是一个分片,该配置需要在索引的 index.routing_partition_size 中进行设置。
当你给索引配置 index.routing_partition_size 以后,数据分片编号的计算公式就变成了以下形式。
这时候,分片编号的计算结果改为由路由值和主键共同决定。对于同一个_routing,hash(_id)%routing_partition_size的可能结果有routing_partition_size种,routing_partition_size值越大,数据在分片上的分发就越均匀,代价是搜索时需要查找更多的分片。这样一来,同一种路由的数据会被分发到routing_partition_size种不同的分片上,从而缓解了同一路由的数据全部分发到某一个分片引起数据存储过于集中的问题。但是routing_partition_size值一旦大于1,由于 join 字段要求同一路由值的文档必须写入同一个分片,支导致join字段在索引中不可使用。
我们也可以自定义 routing 字段来完成数据分发。首先新建一个索引如下。
这里创建了一个带有 3 个主分片的索引,使用到了元字段 _routing,规定了对该索引数据进行增删改查时必须提供路由值
新增一条索引数据,需要带上路由值 routing,否则会报错。
查询索引数据,也要带上路由值 routing。
带上 routing 值之后,只到该路由值对应的分片上去搜索数据;如果不提供路由值时,会检索全部主分片。可见自定义路由能够减少查询的分片数量,从而加快查询速度。在实际项目中巧妙地使用这个功能,对提升查询性能是大有好处的。

1.2.3 索引分片重新索引

由上面可知主分片的数量在索引创建完之后不能修改。但在生产环境中,某些情况我们必须修改主分片 shard 的数量,例如数据量过大,而主分片数量不足,导致单分片的承载压力过大,这时候我们必须增加主分片的数量。
为了解决主分片 shard 数量不能被直接修改这个问题,ElasticSearch 中设置了重新索引机制。重新索引简单来说就是创建一个和原索引库结构属性都基本一样的新的索引库,然后将原索引库中的数据复制到新的索引库当中。在新的索引库中,除了需要变更的地方,比如某些字段的数据类型和分片数,其他的所有属性都一样。
比如我们新建一个索引,和 my-index 的其他属性一致,只有主分片 shard 数量从 1 变成 2,如下所示
执行下面命令,会把索引 my-index 的内容复制到索引 my-index-new 中。

1.3 倒排索引(Inverted Index)

1.3.1 倒排索引是什么

Elasticsearch 使用倒排索引(Inverted Index)实现快速全文搜索。倒排索引是一种将文档内容中的词项(terms)映射到包含这些词项的文档的数据结构。与传统正排索引(文档→内容)相反,倒排索引是(内容→文档)的映射关系,因此称为"倒排"索引。
倒排索引通常由以下部分组成:
  1. 词项字典(Term Dictionary): 包含所有文档中出现的词项的排序列表
  1. 倒排列表(Postings List): 对于每个词项,记录包含该词项的所有文档ID列表
  1. 词项频率(Term Frequency): 记录词项在每个文档中出现的次数
  1. 位置信息(Positions): 记录词项在文档中出现的位置(用于短语查询)
  1. 偏移量(Offsets): 记录词项在文档中的字符偏移量(用于高亮显示)
倒排索引的优点:
  1. 高效检索:可以直接定位包含查询词的文档,无需扫描所有文档
  1. 支持复杂查询:便于实现 AND、OR、NOT 等布尔查询
  1. 空间效率:相比正排索引,通常占用更少存储空间

1.3.2 倒排索引原理

Elasticsearch 的倒排索引本质上是 Lucene 的倒排索引。Elasticsearch 索引和 Lucene 索引的关系如下:
  • 一个 Elasticsearch Index 都是由多个 Shard (primary & replica)构成的。
  • 一个 Shard 本质对应一个 Lucene Index。
  • 一个 Lucene Index 包含多个 Segment。
  • 每一个 Segment 都是一个倒排索引。
Lucene 倒排索引的原理:一段文本经过分析器分析以后就会输出一串单词,这一个个单词就叫做 Term。文档中所有不重复 Term 组成一个列表,对于其中每个 Term,有一个包含它的文档列表,涉及到的概念如下:
  • 索引(Index):类似于数据库的表。在 Lucene 中一个索引是放在一个文件夹中的。所以可以理解索引为整个文件夹的内容。
  • 段(Segment):类似于表的分区。一个索引下可以多个 Segment。
  • 文档(Document):类似于表的一行数据。Document 是索引的基本单位。一个段可以有多个 Document。
  • 域(Field):类似于表的字段。Doument 里可以有多个 Field。Lucene 提供多种不同类型的 Field,例如 StringField、TextField、LongFiled 或 NumericDocValuesField 等。
  • 词(Term):Term 是索引的最小单位。Term 是由 Field 经过 Analyzer(分词)产生。
Lucene 倒排索引的内部结构如下:
notion image
  • Term Index:字典树,用于快速查找 Term。使用 FST 结构,只存储 Term 前缀,通过字典树找到Term所在的块,也就是Term的在字典表中的大概位置,再在块里二分查找,找到对应的Term。
  • Term Dictionary:字典表,用于存储Analyzer分割 后所有Term。使用跳表结构。
  • Posting List:记录表,记录了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。使用Frame Of Reference(FOR)和Roaring bitmaps技术。它不仅仅为文档 id 信息,可能包含以下信息:
    • 文档 id(DocId, Document Id),包含单词的所有文档唯一 id,用于去正排索引中查询原始数据。
    • 词频(TF,Term Frequency),记录 Term 在每篇文档中出现的次数,用于后续相关性算分。
    • 位置(Position),记录 Term 在每篇文档中的分词位置(多个),用于做词语搜索(Phrase Query)。
    • 偏移(Offset),记录 Term 在每篇文档的开始和结束位置,用于高亮显示等。
构建倒排索引的过程:Elasticsearch 会使用多种分析器将文本拆分成用于搜索的词条(Term),然后将这些词条统一化以提高“可搜索性”,整个分析算法称为分析器(Analyzer)
notion image
Analyzer 包含三部分内容:
  1. 字符过滤器(Character Filter):在分词前进行预处理,如去除HTML,字符转换如&转为and。
  1. 分词器(Tokenizer):按照规则切割文档并提取词元(Token),例如遇到空格和标点将文本拆分成词元。
  1. Token过滤器(Token Filter):将切分的词元进行加工,如将大小写统一,增加词条(如jump、leap等同义词)。

2、映射(Mapping)

2.1 映射(Mapping)是什么

映射(Mapping)是 Elasticsearch 中的文档字段结构定义,决定了文档包含的字段如何被存储、索引和检索。官方资料参考
类似关系型数据库中的表结构定义,规定了以下内容:
  • 定义索引包含哪些字段。
  • 定义每个字段的数据类型,比如数值型、字符串型、布尔型等
  • 定义倒排索引相关的配置,比如是否索引、字段如何被分析等
一个典型的映射定义如下:

2.2 映射的定义

以下面的映射结构为例:
这段配置里面定义了 titledescriptionprice 等多个字段,每个字段都可以配置各种参数,参数列表如下:
参数
说明
示例
type
映射字段类型,最重要的映射参数
text
index
是否被索引,设置成false,字段将不会被索引
false
analyzer
指定分词器,分词器在 settings 中定义
ik
boost
增强当前字段的匹配权重
1.23
dynamic
是否开启自动映射,目前支持三个参数:true/false/strict。默认为 true,表示新检测到未定义的的字段时候,自动添加到映射;false 表示不添加到映射;strict 表示当出现未定义的字段,抛出异常并拒绝添加文档
strict
format
自定义日期格式
yyyy-MM-dd
doc_values
对not_analyzed字段,默认都是开启,analyzed字段不能使用,对排序和聚合能提升较大性能,节约内存,如果您确定不需要对字段进行排序或聚合,或者从script访问字段值,则可以禁用doc值以节省磁盘空间
false
fields
可以对一个字段提供多种索引模式,同一个字段的值,一个分词,一个不分词
{"keyword": {"type": "keyword","ignore_above": 256}}
ignore_above
超过长度的字符的文本,将会被忽略,不被索引
100
fielddata
lasticsearch 加载内存 fielddata 的默认行为是延迟加载。 当 Elasticsearch 第一次查询某个字段时,它将会完整加载这个字段所有 Segment 中的倒排索引到内存中,以便于以后的查询能够获取更好的性能。
{"loading" : "eager" }
include_in_all
设置是否此字段包含在 _all 字段中,默认是 true,除非 index 设置成 no 选项
true
index_options
4个可选参数docs(索引文档号) ,freqs(文档号+词频),positions(文档号+词频+位置,通常用来距离查询),offsets(文档号+词频+位置+偏移量,通常被使用在高亮字段)分词字段默认是position,其他的默认是docs
docs
norms
分词字段默认配置,不分词字段:默认{"enable":false},存储长度因子和索引时 boost,建议对需要参与评分字段使用 ,会额外增加内存消耗量
{"enable":true,"loading":"lazy"}
null_value
设置一些缺失字段的初始化值,只有 string 可以使用,分词字段的 null 值也会被分词
NULL
store
是否单独设置此字段的是否存储而从 _source 字段中分离,默认是false,只能搜索,不能获取值
false
search_analyzer
设置搜索时的分词器,默认跟 ananlyzer 是一致的,比如 index 时用 standard+ngram,搜索时用 standard 用来完成自动提示功能
ik
similarity
指定一个字段评分策略,仅仅对字符串型和分词类型有效 ,默认是TF/IDF算法
BM25
映射在不同版本的参数使用有细微区别,如下所示:
version
pattern
5.6.x
可手动启用“index.mapping.single_type: true”,使用 join 字段进行替换
6.x
允许索引使用单一类型,有且仅有一个名称,首选_doc 类型;5.x 版本的索引可延续使用,新版本的索引不再支持父/子方式和 join 类型;6.8中需要在索引创建、模板时需要显示指定 include _ type _ name,不显示申明会默认为 name _ doc
7.x
doc 是路径中的永久部分,并且表示的是 endpoint 类型,而不是 doc 类型;include _ type _ name 参数默认为 false;移除 _default mapping 类型
8.x
不再支持特殊类型, 移除 include_type_name 参数

2.2.1 映射字段类型

映射参数里面最重要的参数是字段类型(通过 type 参数配置)。Elasticsearch 内置了20多种字段类型用于支持多种多样的结构化数据。
1、基本类型
  • 字符串类型,包含 textkeyword 两种类型。
    • text:文本类型(text)是索引中常用的字段类型,文本类型是一种默认会被分词的字段类型,如果不指定,Elasticsearch会使用标准分词器切分文本,并会把切分后的文本保存到索引中。搜索时,只有搜索文本和索引中的文本相匹配的文档才会出现在搜索结果中。
    • keyword:关键字类型(keyword)的字段与文本类型的字段不同,它用于保存不经过分析、处理的原始文本,实际上keyword类型字段在实际开发中很常用,当需要对文本字段进行精准匹配查询时就必须使用keyword类型字段。
  • 数字类型:longintegershortbytedoublefloathalf_floatscaled_float
  • boolean 类型:true/false
  • 日期类型:date 类型,索引中的日期为 UTC 时间格式,其比北京时间晚 8h。另外 json 对象没有日期类型,故 json 中的日期数据会被格式化,具体如下:
    • 字符串类型,例如"2015-01-01"
    • int类型,表示从1970-01-01以来的秒数
    • long类型,表示从1970-01-01以来的毫秒数
  • binary 类型:存储二进制数据,存储之前,需要先用Base64进行编码。该字段类型默认不存储在索引中,也不能用来当搜索条件。
  • range 类型:integer_rangefloat_rangelong_rangedouble_rangedate_range(64-bit 无符号整数,时间戳(单位:毫秒))、ip_range(IPV4 或 IPV6 格式的字符串)
2、array 类型
数组类型,Elasticsearch 不提供专门的数组类型,使用数组类型时,映射中无须用额外的关键字进行定义。任何字段,都可以包含多个相同类型的数值。
3、object 类型
对象类型,你可以直接把一个 JSON 对象作为一个字段写入索引,对象里还可以继续嵌套对象。
在插入数据的时候,Elasticsearch 如果检测到数据值是 JSON 对象,会自动转成 object 类型。缺省设置 type 为 object,因此不用显式定义 type。
也可以显示创建 object 类型字段的索引。
Elasticsearch 在存储对象数据时,默认会将原 JSON 文档扁平化处理,上面 JSON 对象变成以下内容。
这种方式导致一个对象不可以作为一个独立的单元来进行检索,这可能会影响搜索结果的准确性,实际中需要使用嵌套对象(nested object)来作为存储对象的容器。可以通过 user.first 的字段名进行查询
4、nested 类型
嵌套类型可以看成是一个特殊的 object 对象类型,nested 实际上就是 object 的数组,可以让 object 数组独立检索。例如创建一个 user 索引
es 会进行扁平化处理,变成
user.firstuser.last 分别存储多个字段。原来只有两个用户 John SmithAlice White,现在 John 和 Smith 失去了关联,所以下面直接搜索用户名 Alice Smith 也能查询到数据,这就不符合业务预期了。
nested 就是将数组里面的每个 doc 单独变成子文档进行存储,因此在查询时就可以知道具体的结构信息了。要使用 nested 类型必须显示定义映射,否则 es 会自动转成 object 类型
5、geo 类型
有时开发过程中涉及GIS地图相关的功能,例如与经纬度相关的搜索,这时候就需要用到经纬度类型(geo_point)。你可以创建一个经纬度类型的索引,代码如下。

2.2.2 映射的元数据

每个文档都会有一些元数据属性,例如
_index_id 这些就被称为文档的元数据,用来描述文档本身的属性。常见的文档元数据有:
  • _index:文档所在的索引,类似于关系型数据库的database。
  • id:文档的id值。
  • _source:文档的原始 json 数据。
  • size:文档 souce 字段的字节长度,需要插件:mapper-size plugin。
  • _ignored:设置为ignore_malformed=true的所有字段。
  • _routing:路由分片字段。
  • _meta:用于用户自定义元数据。

2.3 创建映射

创建映射有两种方式:
  • 动态映射:Elasticsearch 自动检测并确定字段类型和索引。
  • 显式映射:手动显式定义字段类型和索引。

2.3.1 动态映射(Dynamic mapping)

若向 Elasticsearch 的索引中添加数据的字段是原先未定义的,数据也依然可以被成功添加。Elasticsearch 拥有动态映射机制,会根据添加的数据内容自动识别对应的字段类型并创建索引。支持的数据类型包括:boolean、double、integer、object、array、date。
例如执行下面命令会自动创建索引 user。
查看索引 user 的 mapping 结构。
可以看到 phone 字段被自动映射为 text 类型,并自动增加了 keyword 子字段,说明该文档可以被检索。
动态字段映射的相关参数如下所示:
  • dynamic:开启动态映射的模式。注意已有的字段,是不支持修改 mapping 的,无论 dynamic 配置是什么,这是 Lucene 的特性,倒排索引一旦生成,不支持修改。
    • true:有新字段加入,mapping 也会自动更新
    • false:有新字段加入,mapping 不会被更新,但是新字段会被加入到 _source 元数据中,不过不能被索引查询
    • strict:写入直接失败
  • date_detection:开启日期检测,默认为 true
  • dynamic_date_formats:检测的日期格式,默认为 yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis
  • numeric_detection:开启数值检测,默认为 false
默认映射关系如下:
JSON 类型
Elastic 类型
说明
字符串(包括数字格式)
text
“hello world” --> text ”123” --> text ”123.45” --> text
字符串(日期格式匹配)
date
“2024/02/03” --> date
布尔值
boolean
true or false --> boolean
浮点数
float
123.45 --> double
整数
long (对,不是integer)
123 --> long
对象
Object
数组
由第一个非空数字决定类型
空值 null
忽略
例如在没有新建索引的情况下,插入以下文档数据。
查看索引 user 的 mapping 结构
如果想全局禁止自动创建索引,可以在 elasticsearch.yml 添加下面的配置:

2.3.2 显式映射(Explicit mapping)

因为被动映射的字段可能不太符合我们的需求,所以我们需要显式映射自定义 mapping 的结构。可以使用下面的语法
例如上面那个例子,我们可以手动创建 user 索引。
这时候查看 user 的索引结构,发现 phone 是 keyword 类型。

2.4 查看映射

2.5 修改映射

映射中已经定义的字段不能被更新和删除,因为 Lucene 实现的倒排索引生成后不允许修改,除非 reindex 更新 mapping。除了下面三种情况:
  • 可以添加新的 filed。
  • 已经存在的 fields 里面可以添加 fields。
  • ignore_above 参数可以更新的。
假如先创建索引 user,包含 userage 两个字段。
然后想增加 address 字段,无论是使用下面哪一种方式,es 都可以识别出 addrees 字段,然后增加到映射。
但是如果想把 age 字段改成 text 类型,就会报错 mapper_parsing_exception

3、配置(Setting)

3.1 配置是什么

配置(Setting) 用来定义索引的配置逆袭,包括分片数量、副本数量等。
一个典型的配置如下所示:

3.2 配置的定义

常用配置格式如下:
配置参数有两种类型:
  • 静态配置:只能在创建索引时或在关闭的索引上设置。
  • 动态配置:在索引运行时动态更新,意味着既可以在创建索引时设置,也可以在创建索引后调用 REST 服务进行修改。

3.2.1 索引静态配置

静态配置即索引创建后不能修改。常用参数如下:
  • number_of_shards :主分片数,默认为 5。只能在创建索引时设置,不能修改
  • analysis:设置分词器
  • shard.check_on_startup:是否在索引打开前检查分片是否损坏,当检查到分片损坏将禁止分片被打开。可选值:
    • false:不检测;
    • checksum:只检查物理结构;
    • true:检查物理和逻辑损坏,相对比较耗CPU;
    • fix:类同 与 false,7.0版本后将废弃。默认值:false。
  • codec:数据存储的压缩算法,默认算法为 LZ4,也可以设置成best_compression,best_compression压缩比较好,但存储性能比 LZ4 差
  • routing_partition_size :路由分区数,默认为 1,只能在索引创建时设置。此值必须小于 index.number_of_shards。算法如下( routing 默认值为 _id):
    • 如果设置了该参数,其路由算法为: ( hash(routing) + hash(id) % index.routing_parttion_size ) % number_of_shards
    • 如果不设置该参数,则路由算法为 hash(routing) % number_of_shardings

3.2.2 索引动态配置

动态配置可以在运行时进行动态修改。常用参数如下:
  • number_of_replicas:每个主分片的副本数,默认为 1,该值必须大于等于0
  • auto_expand_replicas:基于可用节点的数量自动分配副本数量,默认为 false(即禁用此功能)
  • refresh_interval:执行刷新操作的频率,这使得索引的最近更改可以被搜索。默认为 1s。可以设置为 -1 以禁用刷新。
  • max_result_window:用于索引搜索的 from+size 的最大值。默认为 10000
  • max_rescore_window: 在搜索此索引中 rescore 的 window_size 的最大值
  • blocks.read_only:设置为 true 使索引和索引元数据为只读,false 为允许写入和元数据更改。
  • blocks.read_only_allow_delete:与blocks.read_only基本类似,唯一的区别是允许删除动作。
  • blocks.read:设置为 true 可禁用对索引的读取操作
  • blocks.write:设置为 true 可禁用对索引的写入操作。
  • blocks.metadata:设置为 true 可禁用索引元数据的读取和写入。
  • max_refresh_listeners:索引的每个分片上可用的最大刷新侦听器数
  • max_docvalue_fields_search:一次查询最多包含开启 doc_values 字段的个数,默认为100。

3.3 创建配置

1、在索引创建时设置配置(settings)。
2、动态更新索引时设置配置(settings)。注意在参数前加 index. 前缀(如 index.number_of_shards)。

3.4 分析器

3.4.1 文本分析的原理

Elasticsearch 规定,一个完整的文本分析过程需要经过大于等于零个字符过滤器、一个分词器、大于等于零个分词过滤器的处理过程。文本分析的顺序是先进行字符过滤器的处理,然后是分词器的处理,最后是分词过滤器的处理。相关说明如下:
  • 字符过滤器(Character Filters):用于对原始文本做简单的字符过滤和转换,例如,Elasticsearch内置的HTML strip字符过滤器可以用于方便地剔除文本中的HTML标签。
  • 分词器(Tokenizer):分词器的功能就是把原始的文本按照一定的规则切分成一个个单词,对于中文文本而言分词的效果和中文分词器的类型有关。分词器还会保留每个关键词在原始文本中出现的位置数据。Elasticsearch内置的分词器有几十种,通常针对不同语言的文本需要使用不同的分词器,你也可以安装一些第三方的分词器来扩展分词的功能。
  • 分词过滤器(Token Filters):用于对用分词器切词后的单词做进一步过滤和转换,例如,停用词分词过滤器(stop token filter)可以把分词器切分出来的冠词a、介词of等无实际意义的单词直接丢弃,避免它们影响搜索结果。
notion image
上面这个图展示了 analysis(文本分析)的过程。analysis 通过 analyzer(分词器)来完成,而 analyzer 在索引配置 settings 里面设置。下面介绍如何使用分析器。

3.4.1 分析器的使用

使用分析器有三种方式:
1、定义索引 settings 的时候指定默认分词器。
分析器(analyzer)属于静态配置,只能在创建索引的时候定义。这里设置的分析器相当于索引的默认分析器,索引新增字段的时候如果没有显式设置分析器,就会使用默认分析器。我们可以使用内置分词器或者第三方分词器,也可以使用自定义的 char_filter、tokenizer、filter 来自由组合。
  1. 使用内置的分析器。这里使用内置的分词器 simple。
    1. 自定义分析器。我们也可以自定义分词器组件 char_filter、tokenizer、filter 的内容,这种方式更加灵活。例如,你可以定义一个分析器,使用字符过滤器过滤掉 HTML 标签,用标准分词器把文本、单词和数字切分到最细粒度,同时添加一个停用词黑名单过滤掉无意义的中文文本,代码如下
      2、定义字段属性的时候指定分析器。如果我们不想用索引默认的分析器,可以在新增字段的时候显式指定分析器。例如下面全局默认分析器为 simple,但是 title 字段指定使用 whitespace 分析器。
      3、可以直接调用分词器 API 对现成的文本进行分词。可以使用 _analyze 的 REST 端点测试分析器的分词效果,这种方式适用于本地调试。有以下三种使用方式:
      • 指定内置分析器分析文本
        • 使用索引字段的分析器分析文本
          • 自定义分析器组件进行文本分析

            3.4.2 内置分析器

            Elasticsearch 内置了8 种分析器,可以直接使用它们。这些分析器有不同的使用效果,具体内容如图所示。
            notion image
            1、Standard Analyzer
            默认的分词器,它会对输入的文本按词的方式进行切分,切分好以后会进行转小写处理,默认的 stopwords 是关闭的。
            notion image
            2、Simple Analyzer
            只包括了 Lower Case 的 Tokenizer,它会按照非字母切分,非字母的会被去除,最后对切分好的做转小写处理,然后接着用刚才的输入文本,分词器换成 simple 来进行分词。
            notion image
            3、Stop Analyzer
            由 Lowe Case 的 Tokenizer 和 Stop 的 Token Filters 组成的,相较于刚才提到的 Simple Analyzer,多了 stop 过滤,stop 就是会把 the,a,is 等修饰词去除。
            notion image
            4、Whitespace Analyzer
            按照空格切分,不转小写
            notion image
            5、Keyword Analyzer
            不分词,直接将输入当做输出
            notion image
            6、Pattern Analyzer
            通过正则表达式的方式进行分词,默认是用 \W+ 进行分割的,也就是非字母的符合进行切分的,运行结果和 Stamdard Analyzer 一致。
            notion image

            3.5 IK 分词器

            在使用 Elasticsearch 进行搜索中文时,Elasticsearch 内置的分词器会将所有的汉字切分为单个字,对用国内习惯的一些形容词、常见名字等则无法优雅的处理,此时就需要用到一些开源的分词器。IK 分词器是业务中普遍采用的中文分词器。

            3.5.1 安装 IK 分词器

            1. 下载插件,注意要下载和使用的Elasticsearch 匹配的版本,否则会启动报错。
            1. 在 Elasticsearch 的安装目录的 Plugins 目录下新建 ik 文件夹,然后将下载的安装包解压到此目录下。
            1. 重启 Elasticsearch。

            3.5.2 使用 IK 分词器

            IK 分词器包含 ik_smart 以及 ik_max_word 两种分词器
            • ik_smart:分词器颗粒度较粗,满足分词场景要求不高的业务
            • ik_max_word:分词颗粒度小,满足业务场景更丰富
            通常,索引时的文本分析使用 ik_max_word 更加合适,而全文检索时的文本分析使用 ik_smart 较为多见。值得注意的是,每个分词结果用偏移量保存了每个分词在原始文本中出现的位置,这类位置信息在全文检索结果高亮展示时会被用到。
            另外,IK 分词器虽然能够识别很多中文词,但是它无法自动发现新词,如果你想扩展自己的词典,则需要把扩展的内容配置到 IK 分词器目录下的 IKAnalyzer.cfg.xml 文件中。
            1、创建索引时设置 IK 分词器
            2、使用 ik_smart 分词器
            使用 ik_smart 分词器测试分词效果
            返回数据
            3、使用 ik_max_word 分词器
            使用 ik_max_word 分词器测试分词效果
            返回数据
            Elasticsearch系列:索引模板Docker系列:修改镜像仓库地址,实现镜像加速
            Loading...