ES 的业务场景主要为超大数据量的查询,当在日常业务中对千万级别的数据量进行分页查询时,使用 Mysql 进行处理很可能出现会超时,此时就可以考虑使用 ES 来进行搜索。
- 正排索引:通过 id(主键,索引)查找内容,再从内容中查找关键字;
- 倒排索引:通过 keyword(关键字,索引)关联 id。
- 词条:索引中存储和查询的最小单元(分词);
- 词典:字典、词条的集合(底层可以是 B+ 树或哈希表);
- 倒排表:……。
- 判断当前搜索的词汇是否在词典中,若是则进行下一步;
- 找到当前词汇在倒排表中的指针,通过倒排表去获取当前词汇对应的文档 id 的列表;
- 通过文档 id 去查找对应的数据(文档)。
PUT 方法具有幂等性,发送同样的内容,返回的结果一样。简单理解,你创建 index 不能创建两个一样的,所以需要符合幂等性(使用 PUT),但是添加数据可以有多条一样的数据,这违反了幂等性所以添加数据不需要使用 PUT,而可以使用 POST。
- 当保存文档数据时,ES 会将文字进行分词,并将拆解后的数据保存到倒排索引中;
- 当进行查询时,ES 也会将查询内容进行分词,并在倒排索引中去进行匹配(全文检索匹配:
match
,类似于模糊查询)。
我们可以为索引数据中的多个字段分别设置不同的搜索配置:
"type": "text"
:该字段为文本,可以被分词;"type": "keyword"
:该字段为关键词,不能被分词,需要精确匹配;"index": true or false
:该字段是否能被索引。
文档分析:将一块文本拆分成适合于倒排索引的独立的词条。
分析器包括:
- 字符过滤器:对特殊内容进行转换。
- 分词器:字符串 -> 词条。
- Token 过滤器:将数据装换为特定的格式。
ES 的内置分析器包括:标准分析器、简单分析器、空格分析器、语言分析器等。
下面的请求会自动创建一个名为 customer
的索引(如果不存在),然后添加一个 ID 为 1 的新文档,同时存储并建立 firstname
和 lastname
字段的索引。
POST /customer/_doc/1
{
"firstname": "Jennifer",
"lastname": "Walters"
}
注意:创建文档(_doc)时,需要指定唯一性标识(即 _id,类似于数据表的主键),既可以手动指定,也可以使用 POST 自动生成。
下面的请求会在 customer
索引下一次性添加多条文本数据。
PUT customer/_bulk
{ "create": { } }
{ "firstname": "Monica","lastname":"Rambeau"}
{ "create": { } }
{ "firstname": "Carol","lastname":"Danvers"}
{ "create": { } }
{ "firstname": "Wanda","lastname":"Maximoff"}
{ "create": { } }
{ "firstname": "Jennifer","lastname":"Takeda"}
注意:这里并没有为每条数据指定唯一性标识(_id),此时该 POST 请求会自动为它们分配唯一性标识(很复杂,不易辨认)。
注意:ES 不允许修改索引信息,因为一旦修改索引,会导致大量的数据重新分配,所以只允许重新建立索引。
下面的请求会获取 customer
索引下 _id
为 1 的文档数据。
GET /customer/_doc/1
注意:一个索引下的每一条数据都由多个字段(这里是
firstname
和lastname
)组成,除此之外,还包括_index
(归属的索引)、_id
(唯一性标识)、_score
(得分,即与搜索文本的匹配程度)等信息。
注意:新文档可以立即从集群中的任何节点获取。
GET index/_search
{
"query": {
"match_all": {...}
}
}
说明:
index
:索引;_search
:搜索该索引下的所有数据;query
:指定查询条件;match_all
:匹配所有数据。
GET index/_search
{
"query": {
"match": {
"FIELD": "TEXT"
"name": "zhang san"
}
}
}
说明:
match
:分词查询,会查出所有FIELD
字段中包含TEXT
中的分词的数据;FIELD
:需要匹配的字段;TEXT
:需要匹配的内容,ES 会将其进行分词("zhang" 和 "san" 会被分为两个关键词)并保存。
GET index/_search
{
"query": {
"term": {
"name": {
"value": "zhang san"
}
}
}
}
说明:
term
:ES 会将TEXT
当作一个完整的关键词去进行匹配(这里的 name 不会做分词,ES 会将 "zhang san" 作为一个完整的关键词)。
中文分词插件:IK 分词器。
ES 的评分机制是一个基于词频和逆文档词频的公式,简称为 TF-IDF 公式。
- TF(term frequency):词频,搜索文本中的各个词条(term)在查询文本中出现了多少次。
- IDF(inverse document frequency):逆文档词频,搜索文本中的各个词条(term)在整个索引的所有文档中出现了多少次,出现的次数越多,说明越不重要,也就越不相关,得分就越低。
得分越高(和搜索文本中的各个词条越匹配)的查询文本会被放在搜索结果的越前面。
事件查询语言(基于时间序列)。
结构化查询语言。
为了支持类 BERT 模型,ES 通过 PyTorch 模型支持大多数最常见的 NLP 任务。
- 同一个索引的数据分为 P0、P1、P2 三个分片。
- 每个分片都可以分为:1 主 + N 备(绿色为主(master),紫色为副本)。
- 新增数据:路由算法(
hash(主键id) % 分片数
)。 - 查询数据:可以查每一个节点(轮询策略)。
注意:同一分片的主备数据不能放在同一个节点上。
- P1 协调节点将更新请求转发到目标节点 P0(主)。
- 考虑到并发写加锁的问题,需要不断地更新(主),并将更新同步到副本。
延时 = 主分片的延时 + 并行写入副本的最大延时。