ElasticSearch 自动补全

embedded/2024/12/22 19:07:30/

1、前言

当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项,根据用户输入的字母,提示完整词条的功能,就是自动补全。

2、安装拼音分词器

Github地址:https://github.com/infinilabs/analysis-pinyin
插件下载地址:https://release.infinilabs.com/analysis-pinyin/stable/

2.1 根据 ES 版本下载指定的插件包

在这里插入图片描述

2.2 安装步骤

  1. 下载插件并解压,重命名为:analysis-pinyin
  2. 上传 analysis-pinyin 到 es 的 plugin 目录
  3. 重启 es
  4. 测试

2.3 测试

DSL语法:

POST /_analyze
{"text":"刘德华","analyzer":"pinyin"
}

测试结果:
在这里插入图片描述

3、自定义分词器

默认的拼音分词器会将每个汉字单独分为拼音。我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。

3.1 ES 分词器(analyzer)组成部分:

  • 字符过滤器(Character Filters):它主要用于在分词之前对原始文本进行预处理。这一步骤可以对文本进行清洗、转换等操作,例如去除 HTML 标签、转换字符大小写、处理特殊字符等。
  • 分词器(Tokenizer):分词器负责将经过字符过滤器处理后的文本按照一定的规则分解为单个的词元(Token)。这些规则可以基于空格、标点符号等进行分词,不同的分词器有不同的分词策略。例如,standard 分词器会按照空格和标点符号来划分词元,将文本拆分成一个个独立的单词或符号。
  • 词元过滤器(Token Filters):词元过滤器用于对分词器产生的词元进行进一步的处理。这可以包括过滤掉停用词(如 “的”、“是” 等在某些情况下对搜索意义不大的词)、词形还原(将词元还原为其基本形式,如将 “running” 还原为 “run”)、同义词替换(将一个词元替换为其同义词,如将 “电脑” 替换为 “计算机”)等操作。

3.2 执行流程图

在这里插入图片描述
说明:特殊符号准换成指定的中文字符,然后借助 ik_smart 进行分词,再通过 pinyin 分词器 转换成 拼音词条。

3.3 测试

DSL 语法

{"settings": {"analysis": {"analyzer": {"py_analyzer": {"tokenizer": "ik_max_word","filter": "py"}},"filter": {"py": {"type": "pinyin",// "keep_separate_first_letter": true,"keep_full_pinyin": false,"keep_joined_full_pinyin": true,"keep_original": true,"limit_first_letter_length": 16,"remove_duplicated_term": true,"none_chinese_pinyin_tokenize": false}}}},"mappings": {"properties": {"name": {"type": "text","analyzer": "py_analyzer","search_analyzer": "ik_smart"}}}
}

字段说明

  • analysis:定义分析(analysis)部分,这里可以指定自定义的分析器、分词器、过滤器或字符过滤器。

    • py_analyzer:自定义分析器名,
      • ik_max_word:中文分词器,它会尽可能多地切分出词语。
      • filter:“py” 是指在分词后将应用的过滤器名称
    • filter:定义过滤器配置信息
      • py: 自定义过滤器名称,与 py_analyzer 指定的 filter 一致
        • type: 指定过滤器类型为pinyin,即拼音过滤器
        • keep_separate_first_letter: 是否保留每个汉字的首字母,
        • keep_full_pinyin: 是否保留全拼
        • keep_joined_full_pinyin: 是否保留连在一起的完整拼音
        • keep_original:是否保留原始文本
        • limit_first_letter_length:限制首字母长度为N个字符
        • remove_duplicated_term: 是否去除重复的词条
        • none_chinese_pinyin_tokenize:是否对非中文内容不进行拼音分词
  • mappings:映射

    • properties:定义文档字段
      • name:字段名
        • type:字段类型
        • analyzer:在索引时使用 py_analyzer 分析器
        • search_analyzer:在搜索时使用 ik_smart 分析器,它会根据上下文智能地选择分词方式

测试结果

在这里插入图片描述

3.4 analyzer 与 search_analyzer 的区别

在 Elasticsearch 中,analyzer 和 search_analyzer 是用来控制文本如何被分析(即分词和转换)的两个不同阶段的设置。它们的主要区别在于应用的时机和目的。

Analyzer

  • 应用时机:analyzer 设置应用于索引时间。当文档被索引时,字段的内容会通过指定的分析器进行处理,然后将结果存储在倒排索引中。
  • 作用:确保数据以一种结构化的方式存储,使得后续的搜索更加高效和准确。例如,中文文本可能会被分词成单个词语,并可能转换为小写或拼音形式等,以便于检索。

Search Analyzer

  • 应用时机:search_analyzer 设置应用于查询时间。当执行搜索请求时,查询字符串会通过指定的搜索分析器进行处理,以便生成与索引中的词条相匹配的形式。
  • 作用:确保查询字符串按照与索引内容相同的方式进行处理,从而提高搜索的相关性和准确性。它允许你对索引和搜索过程使用不同的分析逻辑,比如可以在索引时采用更细粒度的分词,在搜索时采用更智能的分词方式。

区别总结

  • 索引 vs 搜索:analyzer 用于索引阶段的数据预处理,而 search_analyzer 用于搜索阶段的查询字符串预处理。
  • 灵活性:如果未显式定义 search_analyzer,则默认使用字段的 analyzer。但是,有时为了优化搜索体验,你可能希望在搜索时使用不同于索引时的分析策略,这时就可以单独配置 search_analyzer。

4、自动补全查询

ElasticSearch 提供了 Completion Suggester 查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。

对于文档中字段的类型有一些约束

  • 参与补全查询的字段必须是 completion 类型
  • 字段的内容一般是用来补全的多个词条形成的数组

demo 测试

创建索引库

PUT /test
{"mappings": {"properties": {"title":{"type":"completion"}}}
}

插入测试文档

POST test/_doc
{"title": ["Sony", "WH-1000XM3"]
}POST test/_doc
{"title": ["SK-II", "PITERA"]
}POST test/_doc
{"title": ["Nintendo", "switch"]
}

查询所有文档
在这里插入图片描述
自动补全查询
定义 DSL 语法:

GET test/_search
{"suggest": {						// 使用 Suggest 功能"title_suggest": {				// 自定义 Suggest 名称,可以是任何标识符"text": "s",					// 输入文本 "s",表示自动补全的起始字符串"completion":{				// 使用 Completion Suggestion 类型"field":"title",			// 提供自动补全建议的字段"skip_duplicates":true,		// 跳过重复的建议,避免显示重复内容"size":10					// 限制返回建议的数量为 10}}}
}

测试结果:

在这里插入图片描述

5、酒店搜索测试案例

问题:我们的 hotel 索引库还没有设置拼音分词器,需要修改索引库中的配置信息。但是我们知道索引库是无法修改的,只能删除然后重新创建。

分析

  1. 修改 hotel 索引库结构,设置自定义拼音分词器,添加新字段,用来做自动补全,将 brand、suggestion、city等都放进去,作为自动补全的提示。
  2. 修改索引库的 name、all 字段,使用自定义分词器。
  3. 将 brand、business 添加到 suggestion 字段。
  4. 重新导入数据到索引库

5.1 定义 hotel 索引库

DSL 创建 hotel 索引:

PUT /hotel
{"settings": {"analysis": {"analyzer": {"text_analyzer": {"tokenizer": "ik_max_word","filter": "py"},"completion_analyzer": {"tokenizer": "keyword","filter": "py"}},"filter": {"py": {"type": "pinyin",// "keep_separate_first_letter": true,"keep_full_pinyin": false,"keep_joined_full_pinyin": true,"keep_original": true,"limit_first_letter_length": 16,"remove_duplicated_term": true,"none_chinese_pinyin_tokenize": false}}}},"mappings": {"properties": {"id": {"type": "keyword"},"name": {"type": "text","analyzer": "text_analyzer","search_analyzer": "ik_smart","copy_to": "all"},"address": {"type": "keyword","index": false},"price": {"type": "integer"},"score": {"type": "integer"},"brand": {"type": "keyword","copy_to": "all"},"city": {"type": "keyword","copy_to": "all"},"starName": {"type": "keyword"},"business": {"type": "keyword","copy_to": "all"},"location": {"type": "geo_point"},"pic": {"type": "keyword","index": false},"all": {"type": "text","analyzer": "text_analyzer","search_analyzer": "ik_smart"},"suggestion": {"type": "completion","analyzer": "completion_analyzer"}}}
}

5.2 插入 hotel 文档数据

将 brand、city、business 字段内容放入 suggestion 字段中。

public function batchAddDoc()
{$hotels = Hotel::order(['id' => 'asc'])->select();$params = [];foreach ($hotels as $hotel) {$params['body'][] = ['index' => ['_index' => 'hotel','_id'    => $hotel->id,]];# 添加搜索字段$suggestions   = [];$suggestions[] = $hotel->brand;$suggestions[] = $hotel->city;if (strpos($hotel->business, '/') !== false) {$suggestions = array_merge($suggestions, explode('/', $hotel->business));} elseif (strpos($hotel->business, '、') !== false) {$suggestions = array_merge($suggestions, explode('、', $hotel->business));} else {$suggestions[] = $hotel->business;}$params['body'][] = ['id'         => $hotel->id,'name'       => $hotel->name,'address'    => $hotel->address,'price'      => $hotel->price,'score'      => $hotel->score,'brand'      => $hotel->brand,'city'       => $hotel->city,'starName'   => $hotel->star_name,'business'   => $hotel->business,'location'   => $hotel->latitude . ',' . $hotel->longitude,'pic'        => $hotel->pic,'suggestion' => $suggestions];}$result = $this->client->bulk($params);return json($result);
}

5.3 查询 hotel 文档数据

在这里插入图片描述

5.4 自动补全搜索

DSL 语句:

GET hotel/_search
{"suggest": {						        // 使用 Suggest 功能"search_suggest": {				    	// 自定义 Suggest 名称,可以是任何标识符"text": "rj",					      	// 输入文本 "rj",表示自动补全的字符串"completion":{				      	// 使用 Completion Suggestion 类型"field":"suggestion",				// 提供自动补全建议的字段"skip_duplicates":true,				// 跳过重复的建议,避免显示重复内容"size":10				        	// 限制返回建议的数量为 10}}}
}

测试结果:
在这里插入图片描述
PHP 测试示例:

public function search()
{$prefix = 'bj';$result = $this->client->search(['index' => 'hotel','body'  => ['suggest' => ['search_suggest' => ['text' => $prefix,'completion' => ['field' => 'suggestion','skip_duplicates' => true,'size' => 10]]]]]);$options = $result['suggest']['search_suggest'][0]['options'];$data = [];foreach ($options as $option) {$data[] = $option['text'];}return json($data); // 输出:["北京","北京展览馆地区","北京站","北京西站","布吉"]
}

http://www.ppmy.cn/embedded/147889.html

相关文章

第一次面试到第一份offer的经历分享

更多大厂面试经验的视频经验分享看主页 目录: 话不多说,进入正题 从去年九月份开始面试 到现在第一份offer中间经历了大概5个月的时间 我会将我面试过的公司跟一些比较经典的问题分享出来 公司: 1.360 2.奇安信: 3.安询 4.安腾信息技术公司 5.深思科技…

JS字符串方法汇总

String.anchor //创建一个带有名称的 <a> 元素字符串 //已弃用 let str test str.anchor(name) //<a name"name">test</a>String.at let str 1234567 str.at(0) //1 str.at(1) //2 str.at(-1) //7 str.at(-2) //6String.big //已弃用 let …

React+Vite项目框架

基于React Vite 搭建的项目框架&#xff0c;使用ESLint 用于代码检查 、Prettier 用于代码格式化、Husky 用于 Git 钩子、lint-staged 用于暂存文件的检查、commitlint 用于提交信息规范等&#xff0c;实现了路由配置、状态管理、样式响应式设计、亮/暗主题切换等功能。 做这…

QT修改运行窗口的图标

首先&#xff0c;在.pro下添加两行&#xff1a; Debug:DESTDIR $$PWD Release:DESTDIR $$PWD 指定目标文件的路径 指定生成的debug和release文件夹路径在当前项目下 上面是为了防止爆奇怪的错 右键项目添加新文件 选择QT-》QT Resource File 起个名&#xff0c;然后下一步…

Linux系统安装部署Tomcat

1、进入Tomcat官网&#xff0c;官网地址&#xff1a;https://tomcat.apache.org/ 2、点击左侧Download下的Archives按钮 3、选择需要下载的版本 下载地址&#xff1a;https://archive.apache.org/dist/tomcat/ 4、点击自己需要下载的版本&#xff0c;我这里下载的是9.0.6 5、…

AI图像生成利器:Stable Diffusion 3.5本地运行与远程出图操作流程

文章目录 前言1. 本地部署ComfyUI2. 下载 Stable Diffusion3.5 模型3. 演示文生图4. 公网使用Stable Diffusion 3.5 大模型4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 本篇文章将介绍如何在Windows系统电脑本地部署Stable Diffusion 3.5&#xff0c;并利用cpolar…

基于Python3编写的Golang程序多平台交叉编译自动化脚本

import argparse import os import shutil import sys from shutil import copy2from loguru import loggerclass GoBuild:"""一个用于构建跨平台执行文件的类。初始化函数&#xff0c;设置构建的主文件、生成的执行文件名称以及目标平台。:param f: 需要构建的…

调整docker bridge地址冲突,通过bip调整 bridge地址

调整docker bridge地址冲突&#xff0c;通过bip调整 bridge地址 背景步骤 背景 我们在使用docker 过程中&#xff0c;docker 默认bridge地址可能会和一些业务地址相互冲突&#xff0c;需要调整docker bridge 的默认值。 步骤 1.清除当前所有镜像&#xff08;这一步非常关键&…