在我之前的文章 “Elasticsearch: analyzer”,我详细介绍了在 Elasticsearch 中的分析器。分析器在 Elasticsearh 中,它在索引文档的时候需要使用,同时,它也在搜索时,也需要针对搜索的文字进行分词。在今天的文章中,我们来详细介绍分析器是如何在索引及搜索时使用的。
可以在几个级别指定分析器:索引(index)、字段(field)和查询级别(query level)。 在索引级别声明分析器可为所有文本字段提供索引范围内的默认全能分析器。 但是,如果需要在字段级别进一步定制,也可以在字段级别启用不同的分析器。 除此之外,我们还可以在搜索时提供一个不同于索引时间分析器的分析器。 让我们在本节中一一查看这些选项。
索引分析器
有时我们可能需要为不同的字段设置不同的分析器 —— 例如,一个名称字段可能与一个简单的分析器相关联,而信用卡号字段与一个模式(pattern)分析器相关联。 幸运的是,Elasticsearch 允许我们根据需要在各个字段上设置不同的分析器; 同样,我们也可以为每个索引设置一个默认分析器,以便在映射过程中未与特定分析器显式关联的任何字段都将继承索引级别的分析器。 让我们在本节中检查这两种机制。
字段级分析器
我们可以在创建索引的映射定义时在字段级别指定所需的分析器。 例如,下面的代码显示了我们如何在索引创建期间利用它:
1. PUT books_with_field_level_analyzers
2. {
3. "mappings": {
4. "properties": {
5. "name":{
6. "type": "text" #A Standard analyzer is being used here
7. },
8. "about":{
9. "type": "text",
10. "analyzer": "english" #B Set explicitly with an english analyzer
11. },
12. "description":{
13. "type": "text",
14. "fields": {
15. "my":{
16. "type": "text",
17. "analyzer": "fingerprint" #C Fingerprint analyzer on a multi-field
18. }
19. }
20. }
21. }
22. }
23. }
如代码所示,about 和 description 字段是用不同的分析器指定的,除了隐式继承标准分析器的 name 字段。
索引级分析器
我们还可以在索引级别设置我们选择的默认分析器,以下代码清单演示了这一点:
使用默认的分析器创建一个索引
1. PUT books_with_default_analyzer
2. {
3. "settings": {
4. "analysis": {
5. "analyzer": {
6. "default":{ #A Setting this property sets index’s default analyzer
7. "type":"keyword"
8. }
9. }
10. }
11. }
12. }
在此代码清单中,我们实际上将默认的 standard 分析器替换为 keyword 分析器。 你可以通过调用索引上的 _analyse 端点来测试分析器,如下面给出的代码清单所示:
1. POST books_with_default_analyzer/_analyze
2. {
3. "text":"Elasticsearch books"
4. }
上面命令返回:
1. {
2. "tokens": [
3. {
4. "token": "Elasticsearch books",
5. "start_offset": 0,
6. "end_offset": 19,
7. "type": "word",
8. "position": 0
9. }
10. ]
11. }
我们可以使用如下的命令来写入一个文档:
1. PUT books_with_default_analyzer/_doc/1
2. {
3. "name": "Elasticsearch books"
4. }
如果在没有使用默认分析器的情况下,name 肯定是 text 类型的数据,并且以如下的格式进行展现的:
1. "properties": {
2. "name": {
3. "type": "text",
4. "fields": {
5. "keyword": {
6. "type": "keyword",
7. "ignore_above": 256
8. }
9. }
10. }
11. }
在我们创建 books_with_default_analyzer 索引时,我们指定的默认分析器为 keyword。也就是说在没有指定分析器的情形下,它会自动采用 keyword 作为分析器。如果我们使用如下的命令来进行搜索:
1. GET books_with_default_analyzer/_search
2. {
3. "query": {
4. "match": {
5. "title": "Elasticsearch"
6. }
7. }
8. }
我们得到 0 个结果。这是因为 title 字段是 keyword 字段,而我们搜索的内容 Elasticsearch 也只是 “Elasticsearch books” 中的一个部分。
搜索分析器
Elasticsearch 允许我们在查询期间指定不同的分析器,而不是在索引期间使用相同的分析器。 它还允许我们在索引中设置默认分析器 —— 这可以在索引创建期间设置。 让我们看看下面的这两种方法,以及 Elasticsearch 在选择不同级别定义的分析器时遵循的一些规则。
在查询中的分词器
我们还没有完成搜索部分,所以如果下面的代码让你有些困惑,请不要担心:
1. GET books_index_for_search_analyzer/_search
2. {
3. "query": {
4. "match": { #A
5. "author_name": {
6. "query": "M Konda",
7. "analyzer": "simple" #B
8. }
9. }
10. }
11. }
如上面的代码所示,我们在搜索作者时明确指定了分析器(很可能 author_name 字段会使用不同类型的分析器进行索引!)。
在字段级别设置分析器
设置搜索特定分析器的第二种机制是在字段级别。 正如我们为索引目的在字段上设置分析器一样,我们可以在字段上添加一个名为 search_analzyer 的附加属性来指定搜索分析器。 下面的代码演示了这种方法:
1. PUT books_index_with_both_analyzers_field_level
2. {
3. "mappings": {
4. "properties": {
5. "author_name":{
6. "type": "text",
7. "analyzer": "stop",
8. "search_analyzer": "simple"
9. }
10. }
11. }
12. }
如上面的代码所示,author_name 设置了一个用于索引的停止分析器和一个用于搜索时间的 simple 分析器。
索引级别的默认分析器
我们也可以为搜索查询设置一个默认分析器,就像我们为索引时间所做的那样,通过在索引创建时在索引上设置所需的分析器。 以下代码清单演示了该设置:
`
1. PUT books_index_with_default_analyzer
2. {
3. "settings": {
4. "analysis": {
5. "analyzer": {
6. "default_search":{ #A
7. "type":"simple"
8. },
9. "default":{ #B
10. "type":"standard"
11. }
12. }
13. }
14. }
15. }
`
在上面的代码清单中,除了搜索之外,我们还同时设置了索引的默认分析器。 您可能想知道我们是否可以在索引期间而不是在查询期间的运行时在字段级别设置搜索分析器? 下面的代码恰好演示了这一点 —— 在创建索引期间为字段级别的索引和搜索设置不同的分析器:
1. PUT books_index_with_both_analyzers_field_level
2. {
3. "mappings": {
4. "properties": {
5. "author_name":{
6. "type": "text",
7. "analyzer": "standard",
8. "search_analyzer": "simple"
9. }
10. }
11. }
12. }
从上面的代码可以看出,author_name 将使用标准分析器进行索引,而在搜索过程中使用简单分析器。
优先顺序
当引擎在不同级别找到分析器时,引擎会拾取分析器,这是有顺序的。 以下是引擎选择正确分析器的优先顺序:
- 在查询级别定义的分析器具有最高优先级。
- 在定义索引映射时通过在字段上设置 search_analyzer 属性来定义的分析器。
- 在索引级别定义的分析器。
- 如果以上都没有设置,Elasticsearch 引擎会选择在字段或索引上设置的索引分析器。