使用elasticsearch完成多语言搜索的三种方式

文档目标:

基于elasticsearch,实现不同语言搜索特定语言的文档数据;比如输入中文的内容,搜索中文文档数据,输入英文搜索英文文档数据,日韩文类似

方案概述:

方式一:不同的语言使用不同的索引

方式二:使用多字段处理不同语言

方式三:语言检测处理器

目录:

* elasticsearch docker-compose部署

* 中日韩分词插件的安装

* 使用不同的索引保存不同语言文档,并进行搜索

* 使用多字段处理不同语言进行搜索

* 使用语言检测处理器处理文档并进行搜索

* 结论

elasticsearch docker-compose部署

bash 复制代码
version: "3.1"
# 服务配置
services:
  elasticsearch:
    container_name: es01
    image: elasticsearch:8.12.2
    # restart: unless-stopped
    environment:
      - "ES_JAVA_OPTS=-Xms1024m -Xmx1024m"
      - "TZ=Asia/Shanghai"
      - "discovery.type=single-node"
      - "ELASTIC_PASSWORD=123456"
    ports:
      - "9200:9200"  
      - "9300:9300"
    volumes:
      # - ./config:/usr/share/elasticsearch/config
      - elastic-data:/usr/share/elasticsearch/data
      - ./plugins:/usr/share/elasticsearch/plugins
    networks:
      - elastic_net
  kibana:
    container_name: kibana01
    image: kibana:8.12.2
    # restart: unless-stopped
    environment:
      - "TZ=Asia/Shanghai"
      - "I18N_LOCALE=zh-CN"
      - "ELASTICSEARCH_HOSTS=http://elasticsearch:9200"
      - "ELASTICSEARCH_USERNAME=test"
      - "ELASTICSEARCH_PASSWORD=123456"
    ports:
      - "5601:5601"
        #volumes:
        #- ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
    networks:
      - elastic_net
    depends_on:
      - elasticsearch
# 网络配置
networks:
  elastic_net:
    driver: bridge

# docker 卷
volumes:
  elastic-data:

注:启动后需要登录es01容器进行添加用户角色操作:

bash 复制代码
docker exec -it es01 bash
elasticsearch-users useradd test
elasticsearch-users roles -a superuser test
elasticsearch-users roles -a kibana_system test

中日韩分词插件的安装(默认是英文分词器)

分在线安装和离线安装,下面提供一个在线安装方式:

bash 复制代码
# 中文插件ik安装
./bin/elasticsearch-plugin install https://github.com/infinilabs/analysis-ik/releases/download/v8.12.2/elasticsearch-analysis-ik-8.12.2.zip

# 日语分词器安装
bin/elasticsearch-plugin install analysis-kuromoji


# 韩语分词器
bin/elasticsearch-plugin install analysis-nori

使用不同的索引保存不同语言文档,并进行搜索

这里提供一个python代码示例,日韩分词器类似:

python 复制代码
#coding=utf-8
from elasticsearch import Elasticsearch

# 创建Elasticsearch客户端
# es = Elasticsearch()
# 实例化一个ip为localhost,端口为9200,允许超时一小时的es对象
es = Elasticsearch(hosts="localhost", port=9200, timeout=3600, http_auth=('test', '123456'))


# 创建一个中文索引,并指定分词器
chinese_index = es.indices.create(index="my_chinese_index", body={
    "settings": {
        "analysis": {
            "analyzer": {
                "my_chinese_analyzer": {
                    "tokenizer": "ik_smart"
                }
            }
        }
    }
})

# 创建一个英文索引,并指定分词器
english_index = es.indices.create(index="my_english_index", body={
    "settings": {
        "analysis": {
            "analyzer": {
                "my_english_analyzer": {
                    "tokenizer": "standard"
                }
            }
        }
    }
})

# 创建一个中文文档
chinese_document = {
    "title": "中文文档",
    "content": "这是一个中文文档"
}

# 创建一个英文文档
english_document = {
    "title": "English Document",
    "content": "This is an English document"
}

# 将中文文档添加到中文索引
es.index(index="my_chinese_index", body=chinese_document)

# 将英文文档添加到英文索引
es.index(index="my_english_index", body=english_document)

# 搜索中文文档
chinese_result = es.search(index="my_chinese_index", body={
    "query": {
        "match": {
            "content": "中文文档"
        }
    }
})

# 搜索英文文档
english_result = es.search(index="my_english_index", body={
    "query": {
        "match": {
            "content": "English Document"
        }
    }
})

print(chinese_result)
print(english_result)

使用多字段处理不同语言进行搜索

该方式将文本存储在四个字段内并使用四种分析工具进行分析,这可能会浪费我们的宝贵时间和存储空间

创建索引:

bash 复制代码
# 登录kibana控制台操作
PUT /test
{
  "mappings": {
      "properties": {
        "body": {
          "type": "text",
          "fields": {
            "korean_field": {
              "analyzer": "nori",
              "type": "text"
            },
            "japanese_field": {
              "analyzer": "kuromoji",
              "type": "text"
            },
            "chinese_field": {
              "analyzer": "ik_smart",
              "type": "text"
            }
          }
        }
      }
    
  }
}

插入语言数据:

bash 复制代码
POST /test/_doc
{
  "body" : "세계인의 축제, 제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다."
}
POST /test/_doc
{
  "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 time in 30 years after the Seoul Olympic Games in 1988. PyeongChang will be the stage for the Opening and Closing Ceremonies and most snow sports. Alpine speed events will take place in Jeongseon, and all ice sports will be competed in the coastal city of Gangneung."
}
POST /test/_doc
{
  "body" : "第23届冬季奥运会将于2018年2月9日-25日在韩国江原道平昌展开。韩国平昌在第三次申奥之后,于2011年7月6日召开的第123届国际奥委会全会上被选定为2018年冬季奥运会的主办地。由此,韩国自1988年举办首尔夏季奥运会以后,时隔30年,将首次举办冬季奥运会。该届冬奥会的开·闭幕式以及大部分的雪上运动将在平昌进行,而所有冰上运动将在江陵、高山滑雪滑降比赛则将在旌善进行。"
}
POST /test/_doc
{
  "body" : "世界の人々の祝祭、第23回冬季オリンピック大会は大韓民国江原道平昌で2018年2月9日から25日までの17日間、開催されます。大韓民国・平昌は三度の挑戦の末、2011年7月7日に開かれた第123回IOC総会で過半数票を獲得し、2018年冬季オリンピック及びパラリンピックの開催地に選ばれました。これにより1988年ソウルオリンピック開催後30年の時を経てついに、大韓民国で最初の冬季パラリンピックの舞台が繰り広げられます。平昌で開・閉会式とほぼ全ての雪上競技が開催され、江陵では氷上種目全競技が、そして旌善ではアルペンスキー滑降競技が開催される予定です。"
}

搜索测试:

bash 复制代码
# 英文搜索
GET /test/_search
{
  "query": {
    "multi_match": {
      "query": "Olympic Games",
      "fields": [
        "body"
      ]
    }
  }
}
POST /test/_search
{
  "query": {
    "multi_match": {
      "query": "Olympic Games",
      "fields": [
        "body",
        "body.korean_field",
        "body.chinese_field",
        "body.japanese_field"
      ]
    }
  }
}

# 韩文搜索
POST /test/_search
{
  "query": {
    "multi_match": {
      "query": "올림픽대회",
      "fields": [
        "body",
        "body.korean_field",
        "body.chinese_field",
        "body.japanese_field"
      ]
    }
  }
}

# 使用 multi_match 查询,所以主字段(英语)或针对具体语言的子字段会进行匹配
# 日文和中文文本都可能会包含汉字,所以查询可能会返回两种文本。 您既可以显示所有结果,也可以挑选分数最高的结果。
# 日文搜索
POST /test/_search
{
  "query": {
    "multi_match": {
      "query": "オリンピック大会",
      "fields": [
        "body",
        "body.korean_field",
        "body.chinese_field",
        "body.japanese_field"
      ]
    }
  }
}

# 中文搜索
POST /test/_search
{
  "query": {
    "multi_match": {
      "query": "奥运会",
      "fields": [
        "body",
        "body.korean_field",
        "body.chinese_field",
        "body.japanese_field"
      ]
    }
  }
}

使用语言检测处理器处理文档并进行搜索

利用可检测语言的摄取插件 来节省时间和存储空间,摄取管道会检测"正文"字段的语言并且会通过语言检测处理器将检测到的语言放到"语言"字段中,而非将其索引至主字段和三个子字段中

环境问题:需要安装语言检测插件安装,切换成es 8.4.0版本测试(es版本不能高于8.5.0,插件版本比较低,所以需要查看支持的最高版本es来进行安装部署):

bash 复制代码
docker ps |grep es
ec75175a5302   elasticsearch:8.4.0   "/bin/tini -- /usr/l..."   About an hour ago   Up 27 minutes      0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp   es01

docker exec -it es01 bash

bin/elasticsearch-plugin install https://github.com/spinscale/elasticsearch-ingest-langdetect/releases/download/8.4.0.1/ingest-langdetect-8.4.0.1.zip

配置管道:

bash 复制代码
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 = ctx.body;"
      }
    }
  ]
}

创建索引:

bash 复制代码
DELETE test2
PUT /test2
{
    "mappings": {
        "properties": {
            "body": {
                "type": "text"
            },
            "english_field": {
                "type": "text"
            },
            "korean_field": {
                "analyzer": "nori",
                "type": "text"
            },
            "japanese_field": {
                "analyzer": "kuromoji",
                "type": "text"
            },
            "chinese_field": {
                "analyzer": "ik_smart",
                "type": "text"
            }
        }
    }
}

插入文档时,指定语言检测管道

bash 复制代码
PUT /test2/_doc?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 time in 30 years after the Seoul Olympic Games in 1988. PyeongChang will be the stage for the Opening and Closing Ceremonies and most snow sports. Alpine speed events will take place in Jeongseon, and all ice sports will be competed in the coastal city of Gangneung."
}
PUT /test2/_doc?pipeline=langdetect-pipeline
{
  "body" : "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다."
}
PUT /test2/_doc?pipeline=langdetect-pipeline
{
  "body" : "第23届冬季奥运会将于2018年2月9日-25日在韩国江原道平昌展开。韩国平昌在第三次申奥之后,于2011年7月6日召开的第123届国际奥委会全会上被选定为2018年冬季奥运会的主办地。由此,韩国自1988年举办首尔夏季奥运会以后,时隔30年,将首次举办冬季奥运会。该届冬奥会的开·闭幕式以及大部分的雪上运动将在平昌进行,而所有冰上运动将在江陵、高山滑雪滑降比赛则将在旌善进行。"
}
PUT /test2/_doc?pipeline=langdetect-pipeline
{
  "body" : "第23回冬季オリンピック大会は大韓民国江原道平昌で2018年2月9日から25日までの17日間、開催されます。大韓民国・平昌は三度の挑戦の末、2011年7月7日に開かれた第123回IOC総会で過半数票を獲得し、2018年冬季オリンピック及びパラリンピックの開催地に選ばれました。これにより1988年ソウルオリンピック開催後30年の時を経てついに、大韓民国で最初の冬季パラリンピックの舞台が繰り広げられます。平昌で開・閉会式とほぼ全ての雪上競技が開催され、江陵では氷上種目全競技が、そして旌善ではアルペンスキー滑降競技が開催される予定です。"
}

搜索测试:

bash 复制代码
韩语
POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "올림픽대회",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}

英语
POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "Olympic Games",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}

日语
POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "オリンピック大会",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}


中文
POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "奥运会",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}

注:输入日文测试是,还是会返回日文和韩文,所以还是得根据评分高低来获取指定数据

结论

推荐使用第一种,能隔离不同语言文档的搜索结果;方案二的缺点:会将文本存储在四个字段内并使用四种分析工具进行分析,这可能会浪费的大量时间和存储空间;第三方案是第二方案的优化

参考文档:

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

Japanese (kuromoji) analysis plugin | Elasticsearch Plugins and Integrations [8.14] | Elastic

相关推荐
bin91534 小时前
【EXCEL数据处理】000010 案列 EXCEL文本型和常规型转换。使用的软件是微软的Excel操作的。处理数据的目的是让数据更直观的显示出来,方便查看。
大数据·数据库·信息可视化·数据挖掘·数据分析·excel·数据可视化
极客先躯6 小时前
Hadoop krb5.conf 配置详解
大数据·hadoop·分布式·kerberos·krb5.conf·认证系统
2301_786964369 小时前
3、练习常用的HBase Shell命令+HBase 常用的Java API 及应用实例
java·大数据·数据库·分布式·hbase
matlabgoodboy9 小时前
“图像识别技术:重塑生活与工作的未来”
大数据·人工智能·生活
happycao12310 小时前
Flink 03 | 数据流基本操作
大数据·flink
Neituijunsir10 小时前
2024.09.22 校招 实习 内推 面经
大数据·人工智能·算法·面试·自动驾驶·汽车·求职招聘
Data 31712 小时前
Hive数仓操作(十一)
大数据·数据库·数据仓库·hive·hadoop
sp_fyf_202413 小时前
[大语言模型-论文精读] 更大且更可指导的语言模型变得不那么可靠
人工智能·深度学习·神经网络·搜索引擎·语言模型·自然语言处理
qtj-00113 小时前
普通人在刚开始做副业时要注意哪些细节?
大数据·微信·新媒体运营·创业创新
知识分享小能手14 小时前
mysql学习教程,从入门到精通,SQL 修改表(ALTER TABLE 语句)(29)
大数据·开发语言·数据库·sql·学习·mysql·数据分析