--- title: "Easysearch:自定义 Analyzer,其实没你想的那么难" date: 2026-02-20 lastmod: 2026-02-20 description: "深入浅出讲解 Easysearch 自定义 Analyzer 配置方法,详解字符过滤器、分词器、Token过滤器三大组件的组合逻辑,通过商品型号分词实战案例演示 pattern、word_delimiter_graph 等高级配置,掌握 _analyze API 调试技巧" tags: ["自定义分析器", "Analyzer配置", "分词定制"] summary: "提到 Easysearch(或 Elasticsearch)的 分词器(Analyzer),很多开发者的第一反应是:“我就用默认的 standard,或者装个 ik_max_word,够用就行。” 但当你遇到下面这些场景时,标准分词器往往会让你抓狂: 用户搜邮箱 john.doe@example.com,搜 john 能出,搜 gmail 却出不来? 搜商品型号 X-2000-Pro,搜 X2000 居然搜不到? 想让搜索忽略大小写,但又不想忽略某些特定的专有名词? 这时候,你需要的不是寻找更强大的插件,而是自己动手组装一个 Analyzer。 别被“自定义”这三个字吓倒。在 Easysearch 中,自定义分词器就像搭乐高积木一样简单且有趣。 分词器的“乐高”结构 # 一个完整的 Analyzer 由三个核心组件按顺序流水线组成。我们可以把它们想象成三个不同的积木桶,你可以从每个桶里挑出你需要的积木,拼成一个专属的分词器。 字符过滤器(Character Filters) —— 预处理 作用:在分词前对原始字符串进行增删改。 常见积木:html_strip(去 HTML 标签)、mapping(字符替换,如把 & 换成 and)。 数量:0 个或多个。 分词器(Tokenizer) —— 切分 作用:把字符串切成一个个的 Token(词)。 常见积木:whitespace(按空格切)、standard(按语法切)、pattern(按正则切)。 数量:必须且只能有 1 个。 Token 过滤器(Token Filters) —— 加工 作用:对切好的 Token 进行处理(转小写、去停用词、加同义词)。 常见积木:lowercase、stop、synonym、unique。 数量:0 个或多个。 实战:打造一个“商品型号”专用分词器 # 假设我们电商网站有一批商品,型号格式如 CODE-2024-PRO。" --- 提到 Easysearch(或 Elasticsearch)的 **分词器(Analyzer)**,很多开发者的第一反应是:“我就用默认的 `standard`,或者装个 `ik_max_word`,够用就行。” 但当你遇到下面这些场景时,标准分词器往往会让你抓狂: - 用户搜邮箱 `john.doe@example.com`,搜 `john` 能出,搜 `gmail` 却出不来? - 搜商品型号 `X-2000-Pro`,搜 `X2000` 居然搜不到? - 想让搜索忽略大小写,但又不想忽略某些特定的专有名词? 这时候,你需要的不是寻找更强大的插件,而是**自己动手组装一个 Analyzer**。 别被“自定义”这三个字吓倒。在 Easysearch 中,自定义分词器就像**搭乐高积木**一样简单且有趣。 ## 分词器的“乐高”结构 一个完整的 Analyzer 由三个核心组件按顺序流水线组成。我们可以把它们想象成三个不同的积木桶,你可以从每个桶里挑出你需要的积木,拼成一个专属的分词器。 1. **字符过滤器(Character Filters)** —— _预处理_ - _作用_:在分词前对原始字符串进行增删改。 - _常见积木_:`html_strip`(去 HTML 标签)、`mapping`(字符替换,如把 `&` 换成 `and`)。 - _数量_:0 个或多个。 2. **分词器(Tokenizer)** —— _切分_ - _作用_:把字符串切成一个个的 Token(词)。 - _常见积木_:`whitespace`(按空格切)、`standard`(按语法切)、`pattern`(按正则切)。 - _数量_:**必须且只能有 1 个**。 3. **Token 过滤器(Token Filters)** —— _加工_ - _作用_:对切好的 Token 进行处理(转小写、去停用词、加同义词)。 - _常见积木_:`lowercase`、`stop`、`synonym`、`unique`。 - _数量_:0 个或多个。 ## 实战:打造一个“商品型号”专用分词器 假设我们电商网站有一批商品,型号格式如 `CODE-2024-PRO`。 需求: 1. 忽略大小写(搜 `code` 能出)。 2. 支持部分匹配(搜 `2024` 能出)。 3. 支持兼容匹配(搜 `CODE2024` 也能出)。 如果用默认的 `standard`,它会把 `CODE-2024-PRO` 切分成 `[code, 2024, pro]`。但这满足不了“兼容匹配”的需求(搜 `CODE2024` 没法匹配到单独的词)。 我们来 DIY 一个。 ### 第一步:设计蓝图 - **Tokenizer**: 使用 `pattern` 分词器。我们可以定义一个正则,把非字母数字的字符(如 `-`)作为分隔符,或者反过来,只保留字母数字。 - **Token Filter**: 1. `lowercase`:统一转小写。 2. `ngram`(可选):如果我们想支持极强的模糊搜索。 但为了解决 `CODE2024` 这种连写搜 `CODE-2024` 的问题,我们换个思路:**保留原始符号,同时生成不带符号的版本**。或者更简单,在索引时就把标点符号去掉。 让我们尝试一个更通用的配置:**Mapping Char Filter + Whitespace Tokenizer**。 ### 第二步:编写 DSL 我们在创建索引(Index)时,通过 `settings` 来定义这个 Analyzer。 ```json PUT /product_index { "settings": { "analysis": { "char_filter": { "my_hyphen_remover": { "type": "pattern_replace", "pattern": "-", "replacement": "" } }, "analyzer": { "my_product_analyzer": { "type": "custom", "char_filter": [ "html_strip", // 1. 先去 HTML "my_hyphen_remover" // 2. 把横杠去掉 (CODE-2024 -> CODE2024) ], "tokenizer": "standard", // 3. 标准切分 "filter": [ "lowercase" // 4. 转小写 ] } } } }, "mappings": { "properties": { "product_code": { "type": "text", "analyzer": "my_product_analyzer" } } } } ``` _注意:上面的配置是一个激进的例子。它会把 _`CODE-2024`_ 变成 _`code2024`_。这样用户搜 _`code2024`_ 完美匹配。但搜 _`2024`_ 可能就挂了。_ **更优的方案:保留分隔符,但支持多种切分** 通常我们会定义一个 Analyzer,只负责简单的切分和归一化: ```json PUT /product_index_v2 { "settings": { "analysis": { "analyzer": { "code_analyzer": { "type": "custom", "tokenizer": "whitespace", // 按空格切,保留 CODE-2024-PRO 作为一个整体(假设没空格) "filter": [ "lowercase", // 转小写 "word_delimiter_graph" // 神器!智能拆分单词 ] } } } } } ``` 这里用到了 `word_delimiter_graph`,它是处理结构化文本(如 ID、型号、MAC 地址)的神器。它能配置成: - 把 `WiFi` 拆成 `Wi`, `Fi`。 - 把 `CODE-2024` 拆成 `CODE`, `2024`。 - 甚至保留原始词 `CODE-2024`。 ## 调试:不确定的事,测一下 配置好了不敢用?Easysearch 提供了 `_analyze` API,让你在写入数据前就能看到效果。 ```json POST /product_index_v2/_analyze { "analyzer": "code_analyzer", "text": "CODE-2024-PRO" } ``` 观察返回的 Token 列表,看看是否包含了你期望的所有搜索词。 ## 总结 自定义 Analyzer 并不是黑魔法,它只是对 Easysearch 现有能力的**重新排列组合**。 1. **不要迷信默认配置**:默认配置是为了通用性,而你的业务往往有特殊性。 2. **善用 **`_analyze`:所见即所得,调试是自定义分词器的核心步骤。 3. **从需求倒推**:先想好用户会怎么搜(搜 `2024` 还是 `code`),再决定怎么切。 当你开始尝试自定义 Analyzer 时,你就已经从一个 Easysearch 的“使用者”进阶为了“掌控者”。