Elasticsearch:如何使用 Elasticsearch 6.2 搜索中文、日语和韩语文本 - 第 3 部分:语言检测工具

这是我有关中文、日语和韩语文本搜索的系列文章的第 3 部分。如果您还没有阅读有关分析工具的第 1 部分,您可能希望先阅读这一部分。如果您已阅读完第 1 部分,如何使用 Elasticsearch 6.2 搜索中文、日语和韩语文本 - 第 2 部分:多字段介绍了通过多字段对以多种语言编写的文档进行索引和搜索的方法。然而,如果不管任何语言,我们都将文本存储在四个字段内并使用四种分析工具进行分析,这可能会浪费我们的宝贵时间和存储空间。现在,我们将尝试通过语言检测工具来进行优化。和之前一样,文本仍然节选自 https://www.pyeongchang2018.com/en/about-the-games

语言检测工具

我们可以安装并利用可检测语言的摄取插件来节省时间和存储空间。下面的摄取管道会检测“正文”字段的语言并且会通过语言检测处理器将检测到的语言放到“语言”字段中,而非将其索引至主字段和三个子字段中。然后脚本处理器会将“正文”字段的内容复制到具体语言的字段中(english_field、korean_field、japanese_field 或 chinese_field)进行分析。

PUT _ingest/pipeline/langdetect-pipeline
{
  "description": "A pipeline to do whatever",
  "processors": [
    {
      "langdetect": {
        "field": "body",
        "target_field": "language"
      }
    },
    {
      "script": {
        "lang": "painless",
        "source": "if (ctx.language == 'ko') ctx.korean_field = ctx.body; if (ctx.language == 'ja') ctx.japanese_field = ctx.body; if (ctx.language == 'zh-cn') ctx.chinese_field = ctx.body; if (ctx.language == 'en') ctx.english_field = ctxRead More

在本篇博客文章中,我使用的是 kuromojismartcn 和 openkoreantext-analyzer;您也要首先安装这些插件,然后才能创建下面的索引。

DELETE test2
PUT /test2
{  
  "mappings": {
    "docs": {
      "properties": {
        "body": {
          "type": "text"
        },
        "english_field": {
          "type": "text"
        },
        "korean_field": {
          "analyzer": "openkoreantext-analyzer",
          "type": "text"
        },
        "japanese_field": {
          "analyzer": "kuromoji",
          "type": "text"
        },
        "chinese_field": {
          "analyzer": "smartcn",
          "type": "text"
        }
      }
    }
  }
}

对文档进行索引时,您应当指明使用语言检测工具的 langdetect-pipeline 管道。

PUT /test2/docs/1?pipeline=langdetect-pipeline
{
  "body" : "The XXIII Olympic Winter Games will be held for 17 days from 9 to 25 February 2018 in PyeongChang, Gangwon Province, the Republic of Korea. PyeongChang was selected as the host city of the 2018 Olympic Winter Games after receiving a majority vote at the 123rd IOC Session held on 6 July 2011 after three consecutive bids. The Olympic Winter Games will be held in Korea for the first timeRead More

示例: 如果“正文”字段的内容是韩语,则会将其复制到 korean_field,如下所示:

GET /test2/docs/2
=>
{
  "_index": "test",
  "_type": "docs",
  "_id": "2",
  "_version": 1,
  "found": true,
  "_source": {
    "language": "ko",
    "body": "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30Read More

使用多字段的话,我们可以得到相似的搜索结果。这里用到了源文本筛选来筛选结果:

韩语

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "올림픽대회",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.57860667,
    "hits": [
      {
        "_index": "test",
        "_type": "docs",
        "_id": "2",
        "_score": 0.57860667,
        "_source": {
          "body": "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17Read More

英语

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "Olympic Games",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.97953933,
    "hits": [
      {
        "_index": "test",
        "_type": "docs",
        "_id": "1",
        "_score": 0.97953933,
        "_source": {
          "body": "The XXIII Olympic Winter Games will be held for 17 days from 9 to 25 February 2018 inRead More

日语

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "オリンピック大会",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.7469032,
    "hits": [
      {
        "_index": "test2",
        "_type": "docs",
        "_id": "4",
        "_score": 0.7469032,
        "_source": {
          "body": "第23回冬季オリンピック大会は大韓民国江原道平昌で2018年2月9日から25日までの17Read More

中文

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "奥运会",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.49148652,
    "hits": [
      {
        "_index": "test2",
        "_type": "docs",
        "_id": "3",
        "_score": 0.49148652,
        "_source": {
          "body": "第23届冬季奥运会将于2018年2月9日-25日在韩国江原道平昌展开。韩国平昌在第三次申奥之后,于2011年7月6日召开的第123Read More

请注意:由于我们搜索的只是通过具体语言分析工具分析的字段,所以当我们查询日语关键词时,我们只会得到日语文档,同理当我们查询中文关键词时,我们仅会得到中文文档。这与多字段方式有所不同,有关多字段方式,详见如何使用 Elasticsearch 6.2 搜索中文、日语和韩语文本 - 第 2 部分:多字段

担心耗时过长?

如果您担心索引或查询的时间,虽然与使用单字段相比,使用多字段或语言检测工具进行索引时耗时会稍长一点,但是其实它们之间的差别并不大。

index-time.pnguploading.4e448015.gif正在上传…重新上传取消index-time.png

图 1 - 索引 500 份文档所用的时间(MacBook Pro,2.9 GHz Intel Core i7, 16GB 2133 MHz LPDDR3)

使用多字段或语言检测工具查询所用的时间与使用单字段查询所用的时间基本相同。

query-time.pnguploading.4e448015.gif正在上传…重新上传取消query-time.pnguploading.4e448015.gif转存失败重新上传取消query-time.png

图 2 - 进行 500 次查询所用的时间 (MacBook Pro,2.9 GHz Intel Core i7, 16GB 2133 MHz LPDDR3)

通过语言检测工具,我们能够实现比多字段方法更佳的搜索结果,而且还可节省存储空间。Elasticsearch 6.x 甚至还有“稀疏字段改进措施”功能(详见 Elasticsearch 6.0 可节省空间的改善措施)。

附录

multi-lang-scripts.zip

  • index.sh - 测量索引时间的脚本
  • query.sh - 测量查询时间的脚本