Elasticsearch 文本分析与搜索基础
1. 自定义分词器创建索引
可以仿照之前使用自定义组件为字符过滤器类型创建索引的方式,使用包含标准分词器的自定义分析器来创建索引。通过提供
max_token_length
大小来扩展分词器,例如将其设置为 2。创建索引后,可使用
_analyze
API 测试字段,示例代码如下:
POST index_with_custom_standard_tokenizer/_analyze
{
"text": "Bond",
"analyzer": "custom_token_length_analyzer"
}
上述代码会输出两个标记:“Bo” 和 “nd”,符合我们设置的标记大小为 2 个字符的要求。
2. N - gram 和 edge_ngram 分词器
在学习 n - gram 分词器之前,先回顾一下 n - grams、edge_ngrams 和 shingles 的概念:
-
n - grams
:是从给定单词中按给定大小准备的单词序列。例如,对于单词 “coffee”,双字母 n - grams(通常称为 bi - grams)是 “co”、“of”、“ff”、“fe” 和 “ee”;三字母 tri - grams 是 “cof”、“off”、“ffe” 和 “fee”。n - grams 通过滑动字母窗口来准备。
-
edge_ngrams
:生成的单词以原单词的首字母为锚定。以 “coffee” 为例,edge_ngram 生成 “c”、“co”、“cof”、“coff”、“coffe” 和 “coffee”。
2.1 N - gram 分词器
常用于拼写纠正和单词拆分,默认情况下,n - gram 分词器生成的 n - grams 最小大小为 1,最大大小为 2。例如:
POST _analyze
{
"text": "Bond",
"tokenizer": "ngram"
}
输出为
[B, Bo, o, on, n, nd, d]
。可以通过指定配置来自定义
min_gram
和
max_gram
大小,示例代码如下:
PUT index_with_ngram_tokenizer
{
"settings": {
"analysis": {
"analyzer": {
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer"
}
},
"tokenizer": {
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 2,
"max_gram": 3,
"token_chars": [
"letter"
]
}
}
}
}
}
测试该功能的代码如下:
POST index_with_ngram_tokenizer/_analyze
{
"text": "bond",
"analyzer": "ngram_analyzer"
}
会生成 “bo”、“bon”、“on”、“ond” 和 “nd” 这些 n - grams。
2.2 Edge_ngram 分词器
同样可以使用 edge_ngram 分词器生成 edge n - grams,示例代码如下:
"tokenizer": {
"my_edge_ngram_tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 6,
"token_chars": ["letter", "digit"]
}
}
将 edge_ngram 分词器附加到自定义分析器后,可使用
_analyze
API 测试字段:
POST index_with_edge_ngram/_analyze
{
"text": "bond",
"analyzer": "edge_ngram_analyzer"
}
会输出 “b”、“bo”、“bon” 和 “bond” 这些 edge grams,所有单词都以首字母为锚定。
3. 其他分词器
除了上述分词器,还有其他一些分词器,如下表所示:
| 分词器 | 描述 |
| — | — |
| Pattern | 基于正则表达式匹配将字段拆分为标记,默认模式是在遇到非单词字母时拆分单词。 |
| URL and email | 解析字段并保留 URL 和电子邮件,文本中的 URL 和电子邮件将原样输出,不进行分词。 |
| Whitespace | 遇到空白时将文本拆分为标记。 |
| Keyword | 不处理标记,原样输出文本。 |
| Lowercase | 遇到非字母时将文本拆分为标记,并将标记转换为小写。 |
| Path hierarchy | 根据路径分隔符将分层文本(如文件系统文件夹)拆分为标记。 |
4. 分词过滤器
分词器生成的标记可能需要进一步处理,如转换大小写、提供同义词、词干提取、去除撇号或标点符号等。Elasticsearch 提供了近 50 种分词过滤器,以下是几种常见的分词过滤器:
4.1 测试分词过滤器
可以通过将分词过滤器附加到分词器并在
_analyze
API 调用中使用来测试,示例代码如下:
GET _analyze
{
"tokenizer": "standard",
"filter": ["uppercase", "reverse"],
"text": "bond"
}
输出为 “DNOB”,即 “bond” 先转换为大写,再反转。也可以将过滤器附加到自定义分析器,示例代码如下:
PUT index_with_token_filters
{
"settings": {
"analysis": {
"analyzer": {
"token_filter_analyzer": {
"tokenizer": "standard",
"filter": ["uppercase", "reverse"]
}
}
}
}
}
4.2 词干提取过滤器
词干提取是将单词还原为其词根的机制。Elasticsearch 提供了开箱即用的词干提取器,示例代码如下:
POST _analyze
{
"tokenizer": "standard",
"filter": ["stemmer"],
"text": "barking is my life"
}
执行上述代码会生成 “bark”、“is”、“my” 和 “life” 这些标记,“barking” 被转换为 “bark”。
4.3 Shingle 过滤器
Shingles 是在标记级别生成的单词 n - grams。例如,文本 “james bond” 会生成 “james” 和 “james bond”。示例代码如下:
POST _analyze
{
"tokenizer": "standard",
"filter": ["shingle"],
"text": "java python go"
}
执行结果为
[java, java python, python, python go, go]
。可以通过创建带有自定义 shingle 过滤器的自定义分析器来更改默认行为,示例代码如下:
PUT index_with_shingle
{
"settings": {
"analysis": {
"analyzer": {
"shingles_analyzer": {
"tokenizer": "standard",
"filter": ["shingles_filter"]
}
},
"filter": {
"shingles_filter": {
"type": "shingle",
"min_shingle_size": 2,
"max_shingle_size": 3,
"uutput_unigrams": false
}
}
}
}
}
测试代码如下:
POST index_with_shingle/_analyze
{
"text": "java python go",
"analyzer": "shingles_analyzer"
}
会返回
[java python, java python go, python go]
,因为我们配置了过滤器只生成 2 - 和 3 - 单词的 shingles。
4.4 同义词过滤器
同义词是给单词赋予的替代含义。为了在搜索时提供更丰富的用户体验,Elasticsearch 期望我们通过配置带有同义词分词过滤器的分析器来提供一组单词及其同义词。示例代码如下:
PUT index_with_synonyms
{
"settings": {
"analysis": {
"filter": {
"synonyms_filter": {
"type": "synonym",
"synonyms": ["soccer => football"]
}
}
}
}
}
测试代码如下:
POST index_with_synonyms/_analyze
{
"text": "What's soccer?",
"tokenizer": "standard",
"filter": ["synonyms_filter"]
}
会生成 “What’s” 和 “football” 两个标记,“soccer” 被替换为 “football”。还可以通过文件提供同义词,示例代码如下:
PUT index_with_synonyms_from_file_analyzer
{
"settings": {
"analysis": {
"analyzer": {
"synonyms_analyzer": {
"type": "standard",
"filter": ["synonyms_from_file_filter"]
}
},
"filter": {
"synonyms_from_file_filter": {
"type": "synonym",
"synonyms_path": "synonyms.txt"
}
}
}
}
}
5. 搜索基础概述
Elasticsearch 不仅支持简单的搜索功能,还支持考虑多个条件(包括地理空间查询)的高级搜索。搜索分为结构化搜索和非结构化搜索两种类型:
-
结构化搜索
:由词级搜索功能支持,返回的结果不关联相关性评分。Elasticsearch 只检查文档是否完全匹配,不考虑是否接近匹配或匹配程度如何。例如,搜索特定日期范围内的航班、特定促销期间的畅销书等。
-
非结构化搜索
:Elasticsearch 检索与查询密切相关的结果,并根据相关性对结果进行评分,相关性高的结果得分高,排在结果列表的顶部。对文本字段进行搜索会产生相关结果,Elasticsearch 提供全文搜索来处理非结构化数据。
我们使用 RESTful API 与 Elasticsearch 引擎通信,搜索查询可以使用 Query DSL(领域特定语言)或 URL 标准(查询请求)编写。查询发出后,集群中的任何可用节点都会处理请求,并以 JSON 对象的形式返回响应,结果以文档数组的形式包含在对象中。如果查询在文本字段上执行,每个结果会附带相关性评分,评分越高,相关性越高,结果按评分降序排列。
由于 Elasticsearch 采用了精度(Precision)和召回率(Recall)两种策略,返回的结果可能并非 100% 相关。精度是指在索引中可用文档集合中检索到的相关文档的百分比,召回率是指在适用文档集合中检索到的相关文档的百分比。
接下来我们将深入学习搜索的基础知识,包括搜索 API、搜索类型、查询 DSL 以及一些常见的搜索功能,如高亮显示、分页、解释、操作响应字段等。
graph LR
A[搜索请求] --> B{请求类型}
B -->|结构化搜索| C[词级查询]
B -->|非结构化搜索| D[全文搜索]
C --> E[精确匹配结果]
D --> F[相关性评分结果]
E --> G[返回无评分结果]
F --> H[按评分排序结果]
通过以上内容,我们对 Elasticsearch 的文本分析和搜索基础有了较为全面的了解,为后续深入学习搜索功能奠定了基础。
Elasticsearch 文本分析与搜索基础
6. 搜索机制详解
搜索是 Elasticsearch 的核心功能,它能高效且有效地响应用户的查询。当数据完成索引并可用于搜索时,用户能提出各种各样的问题。
6.1 搜索请求处理流程
- 请求接收 :用户通过 RESTful API 发送搜索请求,集群中的任意可用节点会接收该请求。
- 请求解析 :节点对请求进行解析,判断是使用 Query DSL 还是 URL 标准编写的查询。
- 查询执行 :根据查询类型(结构化或非结构化),在索引中执行相应的查询操作。
- 结果收集 :将符合查询条件的文档收集起来。
- 结果处理 :如果是文本字段查询,会为结果计算相关性评分,并按评分降序排列。
- 响应返回 :以 JSON 对象的形式将结果返回给客户端。
6.2 搜索 API 与上下文
搜索 API 是与 Elasticsearch 进行搜索交互的接口,可使用不同的查询语法编写搜索请求。搜索上下文则定义了搜索操作的范围和条件,例如指定索引、文档类型、查询条件等。
7. 搜索类型详细介绍
Elasticsearch 中的搜索类型主要分为 URI 请求和 Query DSL 两种。
7.1 URI 请求
通过在 URL 中添加查询参数来进行搜索,例如:
GET /index_name/_search?q=field_name:value
这种方式简单直接,但对于复杂的查询,参数会变得冗长且难以维护。
7.2 Query DSL
Query DSL 是一种专门用于 Elasticsearch 的领域特定语言,使用 JSON 格式编写查询。它具有更强的表达能力,能处理复杂的查询逻辑。例如:
POST /index_name/_search
{
"query": {
"match": {
"field_name": "value"
}
}
}
为什么更倾向于使用 Query DSL
:
-
表达能力强
:可以构建复杂的查询,如布尔查询、范围查询等。
-
可读性好
:JSON 格式的查询易于理解和维护。
-
灵活性高
:可以方便地组合不同的查询条件。
8. 常见搜索功能
以下是一些常见的搜索功能,能提升搜索的实用性和用户体验。
8.1 高亮显示
高亮显示能在搜索结果中突出显示匹配的关键词。示例代码如下:
POST /index_name/_search
{
"query": {
"match": {
"field_name": "value"
}
},
"highlight": {
"fields": {
"field_name": {}
}
}
}
在响应中,匹配的关键词会被
<em>
标签包裹,方便用户识别。
8.2 分页
当搜索结果较多时,需要进行分页显示。可以使用
from
和
size
参数来实现分页。示例代码如下:
POST /index_name/_search
{
"from": 0,
"size": 10,
"query": {
"match": {
"field_name": "value"
}
}
}
from
表示从第几个结果开始返回,
size
表示每页返回的结果数量。
8.3 解释
解释功能可以帮助我们理解查询是如何执行的,以及每个文档的得分是如何计算的。示例代码如下:
POST /index_name/_search
{
"explain": true,
"query": {
"match": {
"field_name": "value"
}
}
}
响应中会包含每个文档的详细解释信息。
8.4 操作响应字段
可以通过
_source
参数来指定返回的字段,减少不必要的数据传输。示例代码如下:
POST /index_name/_search
{
"_source": ["field1", "field2"],
"query": {
"match": {
"field_name": "value"
}
}
}
这样响应中只会包含
field1
和
field2
字段。
9. 总结
Elasticsearch 的搜索功能丰富多样,涵盖了文本分析、多种分词器和分词过滤器的使用,以及结构化和非结构化搜索等多个方面。
| 要点 | 详情 |
|---|---|
| 文本分析 | 通过内置或自定义分析器对文本字段进行处理,包括分词和归一化两个阶段。 |
| 分词器 | 有标准、n - gram、edge_ngram 等多种分词器,可根据需求选择。 |
| 分词过滤器 | 如词干提取、shingle、同义词等过滤器,能对分词结果进行进一步处理。 |
| 搜索类型 | 分为结构化搜索和非结构化搜索,使用 RESTful API 进行交互,可采用 Query DSL 或 URL 标准编写查询。 |
| 常见功能 | 包括高亮显示、分页、解释、操作响应字段等,提升搜索的实用性和用户体验。 |
graph LR
A[搜索功能] --> B[文本分析]
A --> C[分词器]
A --> D[分词过滤器]
A --> E[搜索类型]
A --> F[常见功能]
B --> G[分词]
B --> H[归一化]
C --> I[标准分词器]
C --> J[n - gram 分词器]
C --> K[edge_ngram 分词器]
D --> L[词干提取过滤器]
D --> M[shingle 过滤器]
D --> N[同义词过滤器]
E --> O[结构化搜索]
E --> P[非结构化搜索]
F --> Q[高亮显示]
F --> R[分页]
F --> S[解释]
F --> T[操作响应字段]
通过对这些知识的掌握,我们能够更好地利用 Elasticsearch 进行数据搜索和分析,满足不同场景下的需求。
超级会员免费看

被折叠的 条评论
为什么被折叠?



