Elasticsearch:分词器中的 normalizer 使用案例

965 阅读2分钟

在我之前的文章 “Elasticsearch:词分析中的 Normalizer 的使用”, 我对 analyzer 中的 normalizer 有一个简单的介绍。今天我将展示使用 normalizer 如何解决问题并降低解决方案的复杂性。

Normalizer 是一种只会为给定输入生成一个 token 的功能。 也就是说,如果你的输入是 “This text is 1 token”,则生成的唯一标记将是 “This text is 1 token”。
然而 Normalizer 有一些限制,比如 Filters,你可以在这里看到适用的过滤器列表

问题

在这个问题中,我们有一个车辆登记索引,其中一个登记信息是车牌。 车牌有一个标准:3 个字母和 4 个数字,我举一些例子:MTB7465,或 MMO9689。

最初,该索引将车牌索引为 keyword,因此无法通过车牌前缀,比如 MTB ,来进行搜索。

我们可以使用 Normalizer 来解决这个问题。

我们可以做两个更改:

  1. 第一个是创建一个 normalizer,它将生成一个 token,但仅使用车牌的文本部分(MTB7412 -> MTB),这样我就可以通过前缀进行搜索。 你可以看到我使用了 pattern-replace 来从车牌中删除数字部分。
  2. 第二部分是创建一个名为 prefix 的字段,它将接收车牌前缀,这是一个 keyword 的字段。

映射/设置如下所示:

`

1.  PUT carplates
2.  {
3.    "settings": {
4.      "analysis": {
5.        "normalizer": {
6.          "default_normalizer": {
7.            "type": "custom",
8.            "char_filter": [
9.              "prefix_plate_char_filter"
10.            ],
11.            "filter": ["lowercase"]
12.          }
13.        },
14.        "char_filter": {
15.          "prefix_plate_char_filter": {
16.            "type": "pattern_replace",
17.            "pattern": """\d+""",
18.            "replacement": ""
19.          }
20.        }
21.      }
22.    },
23.    "mappings": {
24.      "properties": {
25.        "license_plate": {
26.          "type": "keyword",
27.          "fields": {
28.            "prefix": {
29.              "type": "keyword",
30.              "normalizer": "default_normalizer"
31.            }
32.          }
33.        }
34.      }
35.    }
36.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

在索引一些车辆后,我们可以执行测试。比如我们创建如下的文档:



1.  PUT carplates/_doc/1
2.  {
3.    "license_plate": "MTB7465"
4.  }

6.  PUT carplates/_doc/2
7.  {
8.    "license_plate": "MMO9689"
9.  }


执行下面的搜索我们不会得到结果,因为我们只搜索许可证位置的一部分。



1.  GET carplates/_search
2.  {
3.    "query": {
4.      "term": {
5.        "license_plate": "mtb"
6.      }
7.    }
8.  }


现在,如果我们使用我们的 prefix 字段,我们将得到结果。



1.  GET carplates/_search
2.  {
3.    "query": {
4.      "term": {
5.        "license_plate.prefix": "mtb"
6.      }
7.    }
8.  }


上述搜索结果为:



1.  {
2.    "took": 4,
3.    "timed_out": false,
4.    "_shards": {
5.      "total": 1,
6.      "successful": 1,
7.      "skipped": 0,
8.      "failed": 0
9.    },
10.    "hits": {
11.      "total": {
12.        "value": 1,
13.        "relation": "eq"
14.      },
15.      "max_score": 0.6931471,
16.      "hits": [
17.        {
18.          "_index": "carplates",
19.          "_id": "1",
20.          "_score": 0.6931471,
21.          "_source": {
22.            "license_plate": "MTB7465"
23.          }
24.        }
25.      ]
26.    }
27.  }


也许您会想到其他方法来获得相同的结果,但我相信使用 Normalizer 非常实用并且比其他方法更简单,因为你不需要更改字段类型或使用解析器。