Elasticsearch:在分析过程中对数字进行标准化

作者:来自 Elastic spinscale

分析链中的数字标准化

在全文搜索中,一个常见问题是如何处理数字。最基本的方法是将它们完全提取出来,并在范围内作为真实数字进行查询,但在很多情况下,这需要大量分析,而且数字往往只是全文搜索的一部分,比如 iphone 17 或 bed 1.4 m。

问题是,当用户输入搜索时,他们对数字的理解可能与你不同。

1.4 m 和 1,4 m 是相同的吗?事实是,美国和欧洲在大数和分数的分隔符上使用不同的字符。除此之外,用户在搜索引擎中输入数字时,点和逗号常常可以互换使用,尤其是数字较小时。

  • 007 和 7 是相同的吗?取决于你的使用场景。
  • 1.4 m 和 1.40 m 是相同的吗?这取决......你明白我的意思。

那么我们能做些什么来稍微标准化数字呢?

为了这个示例,让我们使用 keep_types token filter,仅保留数字,丢弃分析链中的其他内容:

bash 复制代码
`

1.  POST _analyze
2.  {
3.    "text": "makita führungsschiene 1.4 m, 1,4 m 1,40 1.40",
4.    "tokenizer": "standard",
5.    "filter": [
6.      {
7.        "type": "keep_types",
8.        "types": [
9.          "<NUM>"
10.        ]
11.      }
12.    ]
13.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

这只会返回看起来像数字的 token,无论它们是否包含点或逗号,但会排除其他内容,例如普通单词,比如 makita。

接下来,我们先统一所有带点或逗号的数字。

bash 复制代码
`

1.  POST _analyze
2.  {
3.    "text": "makita führungsschiene 1.4 m, 1,4 m 1,40 1.40",
4.    "tokenizer": "standard",
5.    "filter": [
6.      {
7.        "type": "keep_types",
8.        "types": [
9.          "<NUM>"
10.        ]
11.      },
12.      {
13.        "type": "pattern_replace",
14.        "pattern": "(\\d+)\\,(\\d+)",
15.        "replacement" : "$1.$2"
16.      }
17.    ]
18.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

这只返回 1.4 或 1.40 ------ 很好!所以无论索引了什么,或者用户搜索什么,现在我们总是假设数字使用点,借助 pattern_replace token filter 实现。

如果不关心位置,可以在最后使用 unique token filter ------ 当然也可以省略 norms 以减少索引大小。

你也可以去掉点,只保留数字本身,但这可能导致搜索 1.7 时返回 iphone 17 ------ 同样,这取决于是否希望这样。

接下来,我们去掉前导零:

bash 复制代码
`

1.  POST _analyze
2.  {
3.    "text": "test 007 7 700 000 0",
4.    "tokenizer": "standard",
5.    "filter": [
6.      {
7.        "type": "keep_types",
8.        "types": [
9.          "<NUM>"
10.        ]
11.      },
12.      {
13.        "type": "pattern_replace",
14.        "pattern": "^0+(\\d+)",
15.        "replacement" : "$1"
16.      }
17.    ]
18.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

现在,007 或 000 会被简化为单个数字字符。虽然这可能有用,但请注意,当用户搜索 007 作为零件编号时,可能会返回包含 7 的所有结果,从而增加歧义。

接下来,真正有趣的部分来了:去掉尾随零,但不要弄得太复杂。像往常一样,如果你手头只有正则表达式,你可能会想出一个复杂的正则,但也许预处理可能已经是个好主意。

bash 复制代码
`

1.  POST _analyze
2.  {
3.    "text": "0.100 0.1000 0.101 100 100.0 100.00 100.001",
4.    "tokenizer": "standard",
5.    "filter": [
6.      {
7.        "type": "keep_types",
8.        "types": [
9.          "<NUM>"
10.        ]
11.      },
12.      {
13.        "type": "pattern_replace",
14.        "pattern": "^(\\d+)\\.([0-9])(0+)$",
15.        "replacement" : "$1.$2"
16.      }
17.    ]
18.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

这会返回(至少如果你在请求中添加 filter_path=**.token):

markdown 复制代码
`

1.  {
2.    "tokens": [
3.      {
4.        "token": "0.1"
5.      },
6.      {
7.        "token": "0.1"
8.      },
9.      {
10.        "token": "0.101"
11.      },
12.      {
13.        "token": "100"
14.      },
15.      {
16.        "token": "100.0"
17.      },
18.      {
19.        "token": "100.0"
20.      },
21.      {
22.        "token": "100.001"
23.      }
24.    ]
25.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

你已经可以看到这里还有一些可以改进的地方。100 和 100.0 之间真的有区别吗?也许在这种情况下可以完全去掉尾随的 .0。我相信你会为此想出一个很棒的正则表达式。

让我们把所有步骤整合起来:

bash 复制代码
`

1.  POST _analyze
2.  {
3.    "text": "makita führungsschiene 1.4 m, 1,4 m 1,40 1.40 1.0 1.00 0.100 0.1000 0.101 0.1010 100 100.0 100.00 100.001 0.100 007 700",
4.    "tokenizer": "standard",
5.    "filter": [
6.      {
7.        "type": "keep_types",
8.        "types": [
9.          "<NUM>"
10.        ]
11.      },
12.      {
13.        "type": "pattern_replace",
14.        "pattern": "(\\d+)\\,(\\d+)",
15.        "replacement" : "$1.$2"
16.      },
17.      {
18.        "type": "pattern_replace",
19.        "pattern": "^0+(\\d+)",
20.        "replacement" : "$1"
21.      },
22.      {
23.        "type": "pattern_replace",
24.        "pattern": "^(\\d+)\\.([0-9])(0+)$",
25.        "replacement" : "$1.$2"
26.      }
27.    ]
28.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

在真实的分析链中,你可能会去掉 keep_types filter,并且在适用时尝试将正则表达式组合以提高速度,但这大概是一个不错的起点。

仔细看上面的输出,你会注意到还有一个小问题:0.1010 没有被简化为 0.101。因此,你可能需要对正则表达式做进一步修正 ------ 记住,如果增加一个 token filter 有助于可读性,也是可以的 😊

还有一个实现提示。如果你想确保 pattern replace filter 只针对数字运行,可以使用 condition token filter

原文:discuss.elastic.co/t/dec-2nd-2...

相关推荐
微扬嘴角5 小时前
Springcloud篇9-Elasticsearch-3(数据聚合、自动补全、数据同步、集群)
elasticsearch·spring cloud
真上帝的左手5 小时前
13. 搜索引擎-ES-ES集群
elasticsearch·搜索引擎·jenkins
济南java开发,求内推5 小时前
ES升级至:8.15.3
elasticsearch
真上帝的左手5 小时前
13. 搜索引擎-ES-自动补全
elasticsearch·搜索引擎
真上帝的左手5 小时前
13. 搜索引擎-ES-DSL(Domain Specific Language)
elasticsearch·搜索引擎·数学建模
AI逐月20 小时前
Git 彻底清除历史记录
大数据·git·elasticsearch
管理大亨1 天前
ELK + Redis Docker 企业级部署落地方案
大数据·运维·elk·elasticsearch·docker·jenkins
悟空码字1 天前
SpringBoot 整合 ElasticSearch,给搜索插上“光速翅膀”
java·后端·elasticsearch
Elasticsearch1 天前
开始使用 Elastic Agent Builder 和 Strands Agents SDK
elasticsearch