Elasticsearch Suggesters API详解与联想词自动补全应用

Elasticsearch Suggesters API详解与联想词自动补全应用

  • 引言
  • Elasticsearch Suggesters
    • 1. Term Suggester
      • 实现步骤
      • 示例
    • 2. Phrase Suggester
      • 示例
    • 3. Completion Suggester
      • 创建映射和插入数据
      • 查询示例
    • 4. Context Suggester
      • 示例
  • Completion Suggester
    • 1. 工作原理
    • 2. 使用流程
    • 3. 使用建议和优化
    • 4. 单节点使用优化

引言

在现代搜索引擎的应用场景中,自动补全和拼写检查已成为提升用户搜索体验的重要功能Elasticsearch 作为一款广泛使用的分布式搜索引擎,提供了丰富的 Suggesters API,可以帮助开发者实现精确的自动补全和拼写纠错功能本文将深入探讨 Elasticsearch 中的四种核心 Suggester——Term SuggesterPhrase SuggesterCompletion SuggesterContext Suggester,并通过实际示例展示如何在不同场景下使用这些工具来优化用户的搜索体验

Elasticsearch Suggesters

参考官网:[Suggesters | Elasticsearch Guide 7.17] | Elastic

1. Term Suggester

Term Suggester 主要用于单个词的拼写纠错它通过编辑距离算法,在用户输入的词不存在于索引中时,提供一系列可能的正确拼写Term Suggester 不仅可以返回建议词,还可以显示每个建议词的得分和词频

实现步骤

  • 创建索引并插入数据:确保索引中存在需要搜索的字段
  • 发送 Suggest 请求:在 Elasticsearch 的 _search 端点发送一个包含 suggest 字段的请求

示例

POST /zhoutest/_search
{"suggest": {"my_suggestion": {"text": "hots vlna","term": {"field": "content"}}}
}

在这个例子中,用户输入了错误的短语 hots vlnaTerm Suggester 会建议正确的拼写,比如 hotvolna

2. Phrase Suggester

Phrase Suggester 在 Term Suggester 的基础上更进一步,它可以处理整个短语的拼写纠错Phrase Suggester 考虑了多个词之间的关系,如它们是否同时出现在索引中,以及它们之间的词频和相邻程度

示例

POST /zhoutest/_search
{"suggest": {"my_suggestion": {"text": "lucne and elasticsearch rock","phrase": {"field": "body","highlight": {"pre_tag": "<em>","post_tag": "</em>"}}}}
}

在这个例子中,Phrase Suggester 会识别 lucne 可能是拼写错误,建议改为 lucene,并对其进行高亮显示

3. Completion Suggester

Completion Suggester 专用于快速的前缀搜索和自动补全它通过将分词后的数据编码成 FST(Finite State Transducer)并存储在内存中,以实现极快的查询速度Completion Suggester 非常适用于需要即时反馈的场景,如搜索框的自动补全功能

创建映射和插入数据

首先,需要定义字段类型为 completion 的映射:

PUT localhost:9200/zhoutest/test/_mapping
{"test": {"properties": {"name_suggest": {"type": "completion","analyzer": "simple","search_analyzer": "simple","payloads": true}}}
}

接着插入数据:

PUT 'localhost:9200/zhoutest/test/1?refresh=true'
{"name": "xdy","name_suggest": {"input": ["xdy", "hdu"]}
}

查询示例

POST 'localhost:9200/zhoutest/_suggest?pretty'
{"index-suggest": {"text": "b","completion": {"field": "name_suggest"}}
}

当用户输入 b 时,Completion Suggester 会返回以 b 开头的建议词,如 bananabicycle

4. Context Suggester

Context Suggester 允许基于上下文(如类别或地理位置)提供更精确的建议它能够提高搜索建议的准确性和相关性,适合需要根据用户输入环境来调整建议结果的场景

示例

假设有一个应用程序需要基于用户的地理位置提供建议,可以这样配置 Context Suggester

PUT /zhoutest
{"mappings": {"properties": {"suggest": {"type": "completion","contexts": [{ "name": "location", "type": "geo" }]}}}
}

然后可以插入数据并执行查询,基于用户的地理位置提供更精确的推荐

Completion Suggester

Completion Suggester 是 Elasticsearch 中的一种专用于实现前缀搜索和自动补全功能的 Suggester它通过将数据编码为 FST(有限状态转换器),并将其存储在内存中,从而提供极快的查询速度,非常适用于需要即时反馈的场景,如搜索框的自动补全功能

image-20240829134914853

1. 工作原理

Completion Suggester 的核心是 FST,它是一种压缩的有限状态机,能够快速地匹配前缀并生成补全建议FST 具备以下特性:

  • 前缀匹配:通过编码词汇表中的所有前缀,FST 能够迅速找到与用户输入匹配的前缀并返回相应的候选项
  • 压缩存储:FST 在存储时会自动去除重复前缀,从而显著降低内存占用
  • 即时查询:由于 FST 是内存中操作的,查询速度非常快,能够实时提供搜索建议

2. 使用流程

2.1 创建索引与映射

在使用 Completion Suggester 之前,需要为数据创建索引,并在索引的映射中定义字段类型为 completion可以选择设置 analyzersearch_analyzer 来控制数据如何被分析

示例

PUT /zhoutest
{"mappings": {"properties": {"name_suggest": {"type": "completion"}}}
}

2.2 插入数据

定义好索引映射后,可以向索引中插入数据需要确保将希望进行补全建议的字段作为 input 提供给 completion 类型字段

示例

PUT /zhoutest/_doc/1
{"name": "Elasticsearch","name_suggest": {"input": ["Elasticsearch", "Elastic"]}
}PUT /zhoutest/_doc/2
{"name": "Elastic Stack","name_suggest": {"input": ["Elastic Stack", "ELK Stack"]}
}

在以上示例中,我们为每个文档提供了多个输入选项,用于在用户输入时提供不同的补全建议

2.3 查询建议

插入数据后,可以使用 Completion Suggester 进行查询查询请求会根据用户输入的文本前缀,返回匹配的建议

示例

POST /zhoutest/_search
{"suggest": {"name_suggestion": {"prefix": "Elas",              // 用户输入的前缀"completion": {"field": "name_suggest",     // 指定补全字段"size": 5,                   // 返回的建议数量"fuzzy": {                   // 启用模糊搜索,允许拼写错误"fuzziness": 2}}}}
}

在这个示例中,用户输入了前缀 Elas,Completion Suggester 会返回与该前缀匹配的词汇,如 ElasticsearchElastic Stack

2.4 响应结果

查询结果会返回与输入前缀匹配的建议列表,每个建议包含了补全的文本以及其他元数据(如得分、频率等)

示例

{"suggest": {"name_suggestion": [{"text": "Elas","offset": 0,"length": 4,"options": [{"text": "Elasticsearch","score": 1.0},{"text": "Elastic Stack","score": 1.0}]}]}
}

3. 使用建议和优化

  • 字段优化:在定义 completion 类型字段时,合理选择分析器和映射配置,可以优化查询的性能和结果质量
  • 模糊匹配:如果需要容忍拼写错误,可以启用 fuzzy 配置,允许模糊匹配提升用户使用
  • 内存使用:由于 FST 存储在内存中,建议在高并发或大规模数据场景下,合理配置内存,以确保系统的稳定性

4. 单节点使用优化

如果在单节点数据量较大并且设置的补全字段较多的时候,可能会导致下列报错:

[ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [test_node1] fatal error in thread [elasticsearch[test_node1][management][T#1]], exiting
java.lang.OutOfMemoryError: Java heap spaceat org.apache.lucene.util.fst.OnHeapFSTStore.init(OnHeapFSTStore.java:59) ~[lucene-core-8.6.2.jar:8.6.2 016993b65e393b58246d54e8ddda9f56a453eb0e - ivera - 2020-08-26 10:53:36]at org.apache.lucene.util.fst.FST.<init>(FST.java:461) ~[lucene-core-8.6.2.jar:8.6.2 016993b65e393b58246d54e8ddda9f56a453eb0e - ivera - 2020-08-26 10:53:36]at org.apache.lucene.util.fst.FST.<init>(FST.java:412) ~[lucene-core-8.6.2.jar:8.6.2 016993b65e393b58246d54e8ddda9f56a453eb0e - ivera - 2020-08-26 10:53:36]at org.apache.lucene.search.suggest.document.NRTSuggester.load(NRTSuggester.java:332) ~[lucene-suggest-8.6.2.jar:8.6.2 016993b65e393b58246d54e8ddda9f56a453eb0e - ivera - 2020-08-26 10:54:46]at org.apache.lucene.search.suggest.document.CompletionsTermsReader.suggester(CompletionsTermsReader.java:70) ~[lucene-suggest-8.6.2.jar:8.6.2 016993b65e393b58246d54e8ddda9f56a453eb0e - ivera - 2020-08-26 10:54:46]at org.apache.lucene.search.suggest.document.CompletionTerms.suggester(CompletionTerms.java:71) ~[lucene-suggest-8.6.2.jar:8.6.2 016993b65e393b58246d54e8ddda9f56a453eb0e - ivera - 2020-08-26 10:54:46]at org.elasticsearch.index.engine.CompletionStatsCache.lambda$get$0(CompletionStatsCache.java:93) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.index.engine.CompletionStatsCache$$Lambda$5243/0x00000008018102e0.get(Unknown Source) ~[?:?]at org.elasticsearch.action.ActionListener.completeWith(ActionListener.java:325) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.index.engine.CompletionStatsCache.get(CompletionStatsCache.java:82) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.index.engine.InternalEngine.completionStats(InternalEngine.java:323) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.index.shard.IndexShard.completionStats(IndexShard.java:1073) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.action.admin.indices.stats.CommonStats.<init>(CommonStats.java:207) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.action.admin.indices.stats.TransportIndicesStatsAction.shardOperation(TransportIndicesStatsAction.java:105) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.action.admin.indices.stats.TransportIndicesStatsAction.shardOperation(TransportIndicesStatsAction.java:48) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction$BroadcastByNodeTransportRequestHandler.onShardOperation(TransportBroadcastByNodeAction.java:423) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction$BroadcastByNodeTransportRequestHandler.messageReceived(TransportBroadcastByNodeAction.java:401) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction$BroadcastByNodeTransportRequestHandler.messageReceived(TransportBroadcastByNodeAction.java:388) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor$ProfileSecuredRequestHandler$1.doRun(SecurityServerTransportInterceptor.java:257) ~[?:?]at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor$ProfileSecuredRequestHandler.messageReceived(SecurityServerTransportInterceptor.java:315) ~[?:?]at org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:72) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.transport.TransportService$8.doRun(TransportService.java:800) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:737) ~[elasticsearch-7.9.2.jar:7.9.2]at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) ~[elasticsearch-7.9.2.jar:7.9.2]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[?:?]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[?:?]at java.lang.Thread.run(Thread.java:832) [?:?]
fatal error in thread [elasticsearch[test_node1][management][T#1]], exiting
java.lang.OutOfMemoryError: Java heap spaceat org.apache.lucene.util.fst.OnHeapFSTStore.init(OnHeapFSTStore.java:59)at org.apache.lucene.util.fst.FST.<init>(FST.java:461)

解决方案:

  1. 增加 JVM 堆内存

    • 可以尝试增加 Elasticsearch JVM 的堆内存大小默认情况下,JVM 堆内存的最大值可能较小,可以通过调整 jvm.options 文件中的 -Xmx-Xms 参数来增加堆内存具体的堆内存大小需要根据硬件配置和数据规模来设置,最大修改为:

      -Xms31g
      -Xmx31g
      
  2. 使用es集群配置

    改为使用集群,增加集群数据节点,同时合理划分分片数量,确保数据分片有足够的节点进行分布,可以减轻每个节点的内存负担

    分片配置

    • 分片数量:减少每个索引的主分片数量,同时增加副本分片,以便分布在多个节点上这样可以降低每个节点的内存负担对于大索引,分片的大小通常建议在10GB到50GB之间
    • 分片分配:确保分片均匀分布在集群的所有节点上,以避免单个节点过载

    内存设置

    • JVM堆内存:对于每个节点,JVM堆内存的大小应设置为服务器物理内存的50%左右,但不超过32GB(推荐设置在-Xms-Xmx之间相同的值)
    • 操作系统级别的内存管理:可以配置vm.max_map_count参数,以增加可映射文件数增大file descriptors限制以支持更多的文件句柄

    FST内存占用

    • 减少自动补全字段:由于FST(有限状态转换器)数据结构用于实现自动补全功能,它的内存占用可能很大建议减少自动补全字段的数量或分割这些字段
    • FST外置存储:考虑将FST存储在磁盘上,而不是堆内存中这可以通过适当的索引设置来实现,例如通过调整index.codecbest_compression

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/414515.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

东软 在大健康路上“笨鸟先飞”

若不是东软医疗引入“国家队”通用技术集团作为其最重要的战略投资人&#xff0c;恐怕很多人并不会留意东软“蛰伏”在大健康的赛道上&#xff0c;已有30年。 1997年的一天&#xff0c;沈阳高新技术产业开发区的东大软件园里&#xff0c;创立东软不过6年时间的刘积仁思量着眼前…

并发性服务器

同一时刻能处理多个客户端 多进程&#xff1a; int init_tcp_ser(const char *ip,unsigned short port) {int sockfd socket(AF_INET,SOCK_STREAM,0);if(-1 sockfd){perror("fail socket");return -1;}struct sockaddr_in ser;ser.sin_family AF_INET;ser.sin_por…

tomcat在eclipse中起动成功,无法访问tomcat主页

最近通过geoserver的war包将&#xff0c;geoserver服务部署到了tomcat&#xff0c;发现在eclipse中启动服务后&#xff0c;无法访问localhost&#xff1a;8080主页&#xff0c;geoserver主页&#xff1a;localhost:8080/geoserver/web同样也无法访问。 只需要双击下面的server…

【生成模型系列(初级)】自编码器——深度学习的数据压缩与重构

【通俗理解】自编码器——深度学习的数据压缩与重构 第一节&#xff1a;自编码器的类比与核心概念 1.1 自编码器的类比 你可以把自编码器想象成一个“智能压缩机”&#xff0c;它能够把输入的数据&#xff08;比如图片&#xff09;压缩成一个更小的表示&#xff08;编码&#…

MacOS使用FileZilla通过ssh密钥文件连接远程服务器(已解决)

需求描述 mac电脑,使用filezilla通过FTP连接远程服务器,使用ssh密钥文件代替密码。 版本信息 MacOS:Sonoma 14.5 M3芯片 FileZilla:3.66.5 在这里插入图片描述 连接 1. 创建站点 打开filezilla工具,右上角选择“文件 -> 站点管理器”,打开站点管理器弹窗。 2.…

仿华为车机功能之--修改Launcher3,实现横向滑动桌面空白处切换壁纸

本功能基于Android13 Launcher3 需求:模仿华为问界车机,实现横向滑动桌面空白处,切换壁纸功能(本质只是切换背景,没有切换壁纸)。 实现效果: 实现思路: 第一步首先得增加手势识别 第二步切换底图,不切换壁纸是因为切换壁纸动作太大,需要调用到WallpaperManager,耗…

StringTable

10.1. String的基本特性 String&#xff1a;字符串&#xff0c;使用一对""引起来表示String声明为final的&#xff0c;不可被继承String实现了Serializable接口&#xff1a;表示字符串是支持序列化的。String实现了Comparable接口&#xff1a;表示string可以比较大小…

六. 部署分类器-trt-engine-explorer

目录 前言0. 简述1. 案例运行2. 补充说明3. engine分析结语下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习课程第六章—部署分类器&#xff0c;一起来学习 trt-engine…

更新RK3588开发板的rknn_server和librknnrt.so【这篇文章是RKNPU2从入门到实践 --- 【5】的配套文章】

作者使用的平台有&#xff1a; 一台装有Windows系统的宿主机&#xff0c;在该宿主机上装有Ubuntu 20.04虚拟系统&#xff1b; 瑞芯微RK3588开发板&#xff0c;开发板上的系统为Ubuntu22.04系统&#xff1b; 更新板子的 rknn_server 和 librknnrt.so&#xff0c;rknn_server 和…

借鉴腾讯系统架构从小到大的过程 - 如何做好一个系统设计?不限于(慧哥)慧知开源充电桩平台

推荐一套企业级开源充电桩平台&#xff1a;完整代码包含多租户、硬件模拟器、多运营商、多小程序&#xff0c;汽车 电动自行车、云快充协议&#xff1b;——(慧哥)慧知开源充电桩平台&#xff1b;https://liwenhui.blog.csdn.net/article/details/134773779?spm1001.2014.3001…

倒计时1天!每日一题,零基础入门FPGA

近年来&#xff0c;FPGA工程师凭借着远高于传统软件开发工程师的薪酬&#xff0c;吸引了越来越多的人转行。 然而&#xff0c;入门FPGA并非易事。你需要有清晰的学习路线&#xff0c;包括它的基本组成&#xff08;如可编程逻辑块CLB、输入输出块IOB、内部连线资源等&#xff0…

JS设计模式之“分即是合” - 建造者模式

引言 当我们在进行软件编程时&#xff0c;常常会遇到需要创建复杂对象的情况。这些对象可能有多个属性&#xff0c;属性之间存在依赖关系&#xff0c;或需要按照特定的骤来创建。在这种情况下&#xff0c;使用建造者模式&#xff08;Builder Pattern&#xff09;可以提供一种活…

selenium启动总报错 WebDriverManager总是异常

我的环境用这个自动管理驱动的工具 WebDriverManager 总是报错 尝试过很多方法都没有&#xff0c;只好手动指定浏览器的位置 System.setProperty("webdriver.chrome.driver", "C:\\Users\\27224\\.cache\\selenium\\chromedriver\\win64\\128.0.6613.84\\chrome…

HTTP 协议详解

0x01&#xff1a;HTTP 协议简介 HTTP&#xff08;HyperTextTransferProtocol&#xff0c;超文本传输协议&#xff09;&#xff0c;是一个工作在应用层的协议&#xff0c;它通常运行在 TCP 之上&#xff0c;它指定了客户端以什么样的格式发送信息&#xff0c;以及得到什么样的响…

uniapp微信小程序开发测试获取手机号码

先申请测试号 注意认证但是没有完全认证不要试测试号解密如下 总结我自己的两大坑 1.官网的WXBizDataCrypt需要导入crypto要提前下载但是试了很多次没有效果重新编写这个。将crypto库换成crypto-js库 2.我一直在尝试用下有下面这个界面的测试号不行获取不到用户的code还是啥忘记…

基于SpringBoot+Vue+MySQL的社区维修平台

系统背景 系统管理也都将通过计算机进行整体智能化操作&#xff0c;对于社区维修平台所牵扯的管理及数据保存都是非常多的&#xff0c;例如住户管理、社区公告管理、维修工管理、维修订单管理、接单信息管理、订单信息管理、在线沟通管理、举报信息管理、留言板管理、系统管理等…

记Spring HTTP Invoker远程调用的使用(二)基于Servlet方式,配置servlet映射url-pattern实现

目录 前言 一、概念 二、代码实现 1. 服务端实现 2. 客户端实现 前言 本篇接上一篇记Spring HTTP Invoker远程调用的使用&#xff08;一&#xff09;基于Url映射方式&#xff0c;DispatcherServlet统一处理实现-CSDN博客https://blog.csdn.net/u011529483/article/details/141…

搭建高可用OpenStack(Queen版)集群(九)之部署nova计算节点

一、搭建高可用OpenStack&#xff08;Queen版&#xff09;集群之部署计算节点 一、部署nova 1、安装nova-compute 在全部计算节点安装nova-compute服务 yum install python-openstackclient openstack-utils openstack-selinux -y yum install openstack-nova-compute -y 若yu…

【如何在MacOS升级ruby版本】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

OpenAI Whisper API (InvalidRequestError)

题意: OpenAI Whisper API&#xff08;无效请求错误&#xff09; 问题背景&#xff1a; Im trying to use OpenAI Whisper API to transcribe my audio files. When I run it by opening my local audio files from disk, it worked perfectly. Now Im developing a FastAPI e…