Elasticsearch 自动补全搜索 - autocomplete
作者:来自 Elastic Amit Khandelwal
探索处理自动完成的不同方法,从基础到高级,包括输入时搜索、查询时间、完成建议器和索引时间。
在本文中,我们将介绍如何避免严重的性能错误、Elasticsearch 默认解决方案为何不适用以及重要的实施注意事项。
所有现代网站都在其搜索栏上提供自动补全(autocomplete)功能(输入时搜索),以改善用户体验(没有人愿意输入整个搜索词……)。自动补全必须比标准搜索更快,因为自动完成的全部目的是在用户输入时开始显示结果。如果延迟较高,则会导致用户体验不佳。
以下是著名问答网站 Quora 上的自动完成搜索示例。这是一个很好的自动完成示例:搜索 “elasticsearch auto” 时,以下帖子开始显示在搜索栏中:
注意搜索结果中,有与 Elasticsearch 的自动扩展、自动标记和自动完成功能相关的问题。用户可以进一步输入一些字符来细化搜索结果。
Elasticsearch 中自动完成的各种方法/输入时搜索
有多种方法可以实现自动完成功能,大致分为四大类:
1. Search as you type
这是一种数据类型,旨在方便自动完成查询,而无需事先了解自定义分析器设置。Elasticsearch 内部存储同一文本的各种标记(edge n-gram, shingles),因此可用于前缀和中缀补全。
如果你不熟悉 Elasticsearch 的高级功能(其他三种方法都需要这些功能),那么这种方法会很方便。在 “Search as you type - 边输入边搜索” 中,不需要进行太多配置,即可使其适用于简单的用例和代码示例。更多详细信息请参阅我们的文档。
2. 查询时 - query time
可以通过将匹配查询(match queries)更改为前缀查询(prefix queries)来实现自动完成。在对 token(索引)到 token(搜索查询 token)匹配的匹配查询时,前缀查询(如其名称所建议)从搜索 token 开始的所有 token 匹配,因此匹配的文档数量(结果)很高。
正如所解释的那样,前缀查询不是一个准确的 token 匹配,而是基于字符串中的字符匹配,这是非常昂贵的,并获取了很多文档。 Elasticsearch 内部使用 B+树(B+ tree)类型的数据结构来存储其 token。了解倒排索引(indices)使用的数据结构的内部以及不同类型的查询如何影响性能和结果是有用的。
Elasticsearch 在 7.2 版本中引入了 Match Boolean Prefix 查询(Match boolean prefix query)。这是一种结合了 Match 查询和 Prefix 查询的方式,兼具两者的优势。它在处理多个搜索词时特别有用。例如,如果搜索词为 "foo bar baz",那么与其对所有搜索词执行前缀搜索(这种方式开销大且结果较少),该查询仅对最后一个词执行前缀搜索,而对前面的词进行匹配,且顺序不限。这样可以提高搜索结果的速度和相关性。
3. 完成建议 - Completion suggester
如果你为诸如电子商务和酒店搜索网站等搜索词提供建议,这将很有用。搜索栏提供了查询建议,而不是在实际搜索结果中出现的建议,并且选择了完善建议者提供的建议之一后,它提供了搜索结果。
为了使 completion suggester 工作,必须将 suggestions 索引为任何其他字段。你还可以选择添加权重字段来对建议进行排名。
如果你具有 autocomplete suggestions 的外部来源,例如搜索分析,则这种方法是理想的选择。
代码样本
索引定义
PUT movies { "mappings": { "properties": { "movie_name": { "type": "completion" } } } }
响应:
{ "acknowledged": true, "shards_acknowledged": true, "index": "movies" }
索引 suggstions
PUT movies/_doc/1?refresh { "movie_name" : { "input": [ "Avengers", "Infinity War" ], "weight" : 34 } }
响应:
{ "_index": "movies", "_id": "1", "_version": 1, "result": "created", "forced_refresh": true, "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
搜素
POST movies/_search?pretty { "suggest": { "song-suggest": { "prefix": "inf", "completion": { "field": "movie_name" } } } }
响应:
{ "took": 2, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 0, "relation": "eq" }, "max_score": null, "hits": [] }, "suggest": { "song-suggest": [ { "text": "inf", "offset": 0, "length": 3, "options": [ { "text": "Infinity War", "_index": "movies", "_id": "1", "_score": 1, "_source": { "movie_name": { "input": [ "Avengers", "Infinity War" ] } } } ] } ] } }
4. 索引时 - index time
有时,要求只是 prefix completion 或 autocomplete 中的 infix 完成。使用 Custom-Analyzers 看到自动完成的实现并不少见,这涉及以与用户的搜索词相匹配的方式索引令牌。
如果我们继续进行示例,我们将查看由 “elasticsearch Autocopterete”,“ elasticsearch Auto-Tag”,“ elasticsearch auto Scaling” 和 “Elasticsearch automatically” 组成的文档。默认的 analyzer 不会为 “autocomplete”,“autoscaling” 和 “automatically” 产生任何部分 token,并且搜索 “auto” 不会产生任何结果。
为了克服上述问题, edge ngram 或 n-gram tokenizer 用于在 Elasticsearch 中索引 token,如文档中所述,并搜索时分析器(search time analyzer )以获得自动完成结果。
上述方法使用了 Match 查询,这种查询速度较快,因为它基于字符串比较(使用哈希码)。此外,索引中精确匹配的 token 相对较少,从而进一步提高了查询效率。
性能考虑
上述几乎所有方法在较小的搜索负载的较小数据集上都可以正常工作,但是当你有大量索引获得大量自动索引建议查询时,上述查询的 SLA 和性能是必不可少的。以下要点应帮助你选择最适合你需求的方法:
- Ngram 或 Edge Ngram token 会显著增加索引大小,因此需要根据应用需求和系统容量合理设定
min_gram
和max_gram
的限制。合理规划可以在生产环境中避免许多问题。 - 允许空前缀或仅包含少量字符的前缀查询可能会匹配索引中的所有文档,从而导致整个集群崩溃。因此,最佳实践是仅在少数字段上执行前缀查询,并限制前缀查询的最小字符数。上述的 Match Boolean Prefix 查询可以很好地解决这一问题。
- Elasticsearch 提供的 "search_as_you_type" 数据类型会以多种格式对输入文本进行分词。由于它是 Elasticsearch 提供的标准解决方案,无法满足所有业务需求,因此在使用时应仔细检查业务场景下的所有边界情况。此外,由于该方法会以多种格式对字段进行分词,可能会增加 Elasticsearch 索引存储的大小。
- Completion Suggest 采用独立索引的方式存储建议词,但无法用于获取搜索结果,因此适用于自动补全场景,而不适用于一般的搜索需求。
- 索引时优化(Index-time approach)速度快,因为查询时的计算开销较小,但它需要更多的前期工作,例如 重新索引(reindexing)、容量规划(capacity planning)和额外的磁盘存储成本。相比之下,查询时优化(Query-time approach)更容易实现,但搜索查询成本更高。理解这一权衡(trade-off)非常重要,因为在大多数情况下,用户需要在两者之间做出选择,并清楚其影响,以便解决各种性能问题。
想获得 Elastic 认证吗?找出何时进行下一个 Elasticsearch工程师培训!
Elasticsearch 包含新功能,可帮助你为用例构建最佳的搜索解决方案。潜入我们的示例笔记本上,以了解更多信息,开始免费的云试验,或者现在在本地机器上尝试 Elastic。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
“NGINX邮件组历史”论坛上线了
NGINX 向云原生演进,All inOpenNJet 背景 长久以来,forum.nginx.org 作为nginx邮件讨论组的论坛形式,是NJet以及广大的NGINX开发人员交流、讨论的主要资源站点,尤其是方便的搜索能力,使得开发人员可以方便的查询历史讨论信息。但很遗憾,该站点已经下线,F5推出了community.nginx.org, 但并没有把历史数据迁移过来。 OpenNJet因此决定从NGINX email 讨论组的邮件归档中,重构一个论坛,便于开发人员进行搜索历史数据。同时,该论坛直接采用了NJet实现的python应用服务器框架,也是NJet能力的一个证明 设计 部署架构 出于对NJet应用服务器能力的展示要求,NJet选择了基于python语言,django架构的开源论坛软件spirit(https://github.com/nitely/Spirit),不需要采用传统的nginx 代理+python应用服务器的模式,spirit安装后,将直接在NJet进程内部运行,如下图展示 Email archive到论坛的转换模型 受限于spirit的模型, email arc...
- 下一篇
DeepSeek “源神”启动!「GitHub 热点速览」
上周,DeepSeek 官方宣布将陆续发布 5 个开源项目 。本周一开源社区就迎来了首发之作------FlashMLA!该项目开源后,不到一天 Star 数已突破 6k,并且还在以惊人的速度持续飙升。 GitHub 地址:github.com/deepseek-ai/FlashMLA FlashMLA 是一个针对 Hopper GPU 优化的高效 MLA(Multi-Head Latent Attention)解码内核,能够显著提升大规模语言模型(LLM)的推理效率。对于普通用户来说,就是用了 FlashMLA 同样的 GPU 硬件条件下,LLM 的聊天机器人不仅可以更快速地响应,还能处理更长的文本。 Tips:Hopper 是英伟达在 2022 年推出的 GPU 架构,采用 NVIDIA Hopper GPU 架构的显卡包括 H100、H200、H800 系列。 回顾上周的热门开源项目,微软开源的屏幕解析 AI 工具 OmniParser 表现亮眼(9k Star/周),它能够将用户界面的截图解析为结构化、易于理解的元素,提升 AI 理解 GUI 的能力。让 AI 能够像人类一样与...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS关闭SELinux安全模块
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Mario游戏-低调大师作品
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8编译安装MySQL8.0.19
- CentOS6,7,8上安装Nginx,支持https2.0的开启