Elasticsearch 自动补全搜索 - autocomplete
作者:来自 Elastic Amit Khandelwal

探索处理自动完成的不同方法,从基础到高级,包括输入时搜索、查询时间、完成建议器和索引时间。
在本文中,我们将介绍如何避免严重的性能错误、Elasticsearch 默认解决方案为何不适用以及重要的实施注意事项。
所有现代网站都在其搜索栏上提供自动补全(autocomplete)功能(输入时搜索),以改善用户体验(没有人愿意输入整个搜索词……)。自动补全必须比标准搜索更快,因为自动完成的全部目的是在用户输入时开始显示结果。如果延迟较高,则会导致用户体验不佳。
以下是著名问答网站 Quora 上的自动完成搜索示例。这是一个很好的自动完成示例:搜索 “elasticsearch auto” 时,以下帖子开始显示在搜索栏中:

注意搜索结果中,有与 Elasticsearch 的自动扩展、自动标记和自动完成功能相关的问题。用户可以进一步输入一些字符来细化搜索结果。
Elasticsearch 中自动完成的各种方法/输入时搜索
有多种方法可以实现自动完成功能,大致分为四大类:
- Search-as-you-type
- Query time
- Completion suggester
- Index time
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。
原文:Elasticsearch autocomplete search - Elasticsearch Labs
相关文章:
Elasticsearch 自动补全搜索 - autocomplete
作者:来自 Elastic Amit Khandelwal 探索处理自动完成的不同方法,从基础到高级,包括输入时搜索、查询时间、完成建议器和索引时间。 在本文中,我们将介绍如何避免严重的性能错误、Elasticsearch 默认解决方案为何不适用以及重要的…...
快速入门Springboot+vue——MybatisPlus多表查询及分页查询
学习自哔哩哔哩上的“刘老师教编程”,具体学习的网站为:7.MybatisPlus多表查询及分页查询_哔哩哔哩_bilibili,以下是看课后做的笔记,仅供参考。 多表查询 多表查询[Mybatis中的]:实现复杂关系映射,可以使…...
工程师 - VSCode的AI编码插件介绍: MarsCode
豆包 MarsCode MarsCode AI: Coding Assistant Code and Innovate Faster with AI 豆包 MarsCode - 编程助手 安装完成并使能后,会在下方状态栏上显示MarsCode AI。 安装完并重启VSCode后,要使用这个插件,需要注册一下账号。然后授权VSCod…...
VOS3000线路对接、路由配置与路由分析操作教程
一、VOS3000简介 VOS3000是一款常用的VoIP运营平台,支持多种线路对接和路由配置,适合新手快速上手。本教程将带你了解如何对接线路、配置路由以及进行路由分析。 二、线路对接 准备工作 获取线路信息:从供应商处获取线路的IP地址、端口、用…...
学习Linux准备2
使用win10系统带的wsl配置ubuntu系统,通过wsl功能我们可以更简单更轻松的获得Linux系统环境。 首先开启Windows自带的wsl功能 打开控制面板,选中启用或关闭Windows功能 这里我们点击进入 将上图红√点击上,点击确定,然后重新启动…...
Java IO 和 NIO 的基本概念和 API
一、 Java IO (Blocking IO) 基本概念: Java IO 是 Java 平台提供的用于进行输入和输出操作的 API。Java IO 基于 流 (Stream) 的模型,数据像水流一样从一个地方流向另一个地方。Java IO 主要是 阻塞式 I/O (Blocking I/O),即线程在执行 I/O …...
【数据结构】快指针和慢指针
一、 给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。 要求:只遍历一遍链表 可以使用快慢指针:fast 一次走两步,slow 一次走一步。当 fast NULL(偶数个结点)或…...
四、综合案例(Unity2D)
一、2D渲染 1、2D相机基本设置 上面是透视,下面是正交 2、图片资源 在Unity中,常规图片导入之后,一般不在Unity中直接使用,而是转为精灵图Sprite 将图片更改为即可使用Unity内置的图片切割功能 无论精灵图片是单个的还是多个的…...
全面汇总windows进程通信(三)
在Windows操作系统下,实现进程间通信(IPC, Inter-Process Communication)有几种常见的方法,包括使用管道(Pipe)、共享内存(Shared Memory)、消息队列(Message Queue)、命名管道(Named Pipe)、套接字(Socket)等。本文介绍如下几种: RPC(远程过程调用,Remote Pr…...
Caffeine:高性能的Java本地缓存库
文章目录 引言什么是Caffeine?Caffeine的主要特点Caffeine的使用方法Caffeine与Google Guava Cache的对比Caffeine与Ehcache的对比总结 引言 在现代软件开发中,缓存是提高应用性能的重要手段之一。通过缓存,可以减少对数据库或其他外部系统的…...
Codes 开源免费研发项目管理平台 2025年第一个大版本3.0.0 版本发布及创新的轻IPD实现
Codes 简介 Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台,支持云端认证、本地部署、全部功能开放,并且对 30 人以下团队免费。它通过创新的方式简化研发协同工作,使敏捷开发更易于实施。并提供低成本的敏捷开发解决方案࿰…...
flowable 全生命周期涉及到的api及mysql表
要了解Flowable从流程创建到审批过程中涉及的API和MySQL表。之前对工作流引擎有一些基础了解,但具体到Flowable的细节可能不太熟悉。需要先回忆一下Flowable的基本概念,比如流程定义、流程实例、任务、执行实例等,然后逐步思考每个步骤会用到…...
Golang | 每日一练 (3)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Golang | 每日一练 (3)题目参考答案map 实现原理hmapb…...
【java】类声明的两种形式
在 Java 中,类的声明有两种形式: public class Test class Test 它们的区别主要在于访问权限和文件名的要求。下面我会详细解释这两种形式的区别。 1. public class Test 访问权限: public 表示这个类是公共的,可以被其他包&am…...
VSCode 中设置 Git 忽略仅因时间戳修改导致的文件变更【使用deepseek生成的一篇文章】
在 VSCode 中设置 Git 忽略仅因时间戳修改导致的文件变更,可通过以下步骤实现: 确认是否为纯时间戳修改 首先确认文件的修改是否仅涉及时间戳,使用终端运行: git diff -- <file>若输出为空但 Git 仍提示修改,可…...
Docker入门及基本概念
让我们从最基础的概念开始逐步理解。假设你已经准备好了docker 环境。 第一步,让我们先通过实际操作来看看当前系统中的镜像(images)和容器(containers)状态: docker images # 查看所有镜像 docker ps -a # 查看所有容器(包括未运行…...
java八股文-消息队列
一、MQ基础篇 1. 什么是消息队列? 消息队列(MQ)是分布式系统中实现异步通信的中间件,解耦生产者和消费者。 2. 使用场景有哪些? 异步处理(如注册后发送邮件)系统解耦(不同服务通过…...
设备唯一ID获取,支持安卓/iOS/鸿蒙Next(uni-device-id)UTS插件
设备唯一ID获取 支持安卓/iOS/鸿蒙(uni-device-id)UTS插件 介绍 获取设备唯一ID、设备唯一标识,支持安卓(AndroidId/OAID/IMEI/MEID/MacAddress/Serial/UUID/设备基础信息),iOS(Identifier/UUID),鸿蒙&am…...
基于Springboot医院预约挂号小程序系统【附源码】
基于Springboot医院预约挂号小程序系统 效果如下: 小程序主页面 帖子页面 医生账号页面 留言内容页面 管理员主页面 用户管理页面 我的挂号页面 医生管理页面 研究背景 随着信息技术的飞速发展和互联网医疗的兴起,传统的医疗服务模式正面临着深刻的变…...
微信小程序 - 页面跳转(wx.navigateTo、wx.redirectTo、wx.switchTab、wx.reLaunch)
API 跳转 1、wx.navigateTo (1)基本介绍 功能:保留当前页面,跳转到应用内的某个页面,使用该方法跳转后可以通过返回按钮返回到原页面 使用场景:适用于需要保留当前页面状态,后续还需返回的情…...
如何手动设置u-boot的以太网的IP地址、子网掩码、网关信息、TFTP的服务器地址,并进行测试
设置IP地址 运行下面这条命令设置u-boot的以太网的IP地址: setenv ipaddr 192.168.5.9设置子网掩码 运行下面这条命令设置u-boot的以太网的子网掩码: setenv netmask 255.255.255.0设置网关信息 运行下面这条命令设置u-boot的网关信息: …...
小红书运营教程(内容笔记01)
# 小红书笔记引流实战指南:合规涨粉与精准引流策略## 一、引流底层逻辑:平台算法与用户心理### 1.1 小红书流量推荐机制 ```mermaid graph TD A[笔记发布] --> B(机器初审) B --> C{内容质量检测} C -->|通过| D[进入初级流量池200-500曝光] D --> E{互动率达标?…...
tortoiseGit的使用和上传拉取
tortoiseGit的使用和上传拉取 下载TortoiseGit 通过网盘分享的文件:tortoiseGit.zip 链接: https://pan.baidu.com/s/1EOT_UsM9_OysRqXa8gES4A?pwd1234 提取码: 1234 在电脑桌面新建文件夹并进入 右击鼠标 将网址复制上去 用户名和密码是在git注册的用户名和…...
IDEA通过Maven使用JBLJavaToWeb插件创建Web项目
第一步:IDEA下载JBLJavaToWeb插件 File--->Settings--->Plugins--->Marketplace搜索: JBLJavaToWeb 第二步:创建普通Maven工程 第三步: 将普通Maven项目转换为Web项目...
【新手初学】SQL注入之二次注入、中转注入
二次注入 一、概念 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。 二、原理 防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处…...
【第四节】C++设计模式(创建型模式)-Builder(建造者)模式
目录 引言 一、Builder 模式概述 二、Builder 模式举例 三、Builder 模式的结构 四、Builder 模式的实现 五、Builder 模式的优缺点 六、总结 引言 Builder 模式是一种创建型设计模式,旨在将复杂对象的构建过程与其表示分离。通过一步步构建对象,…...
本地部署AI模型 --- DeepSeek(二)---更新中
目录 FAQ 1.Failed to load the model Exit code: 18446744072635812000 FAQ 1.Failed to load the model Exit code: 18446744072635812000 问题描述: 🥲 Failed to load the model Error loading model. (Exit code: 18446744072635812000). Unkn…...
MariaDB 历史版本下载地址 —— 筑梦之路
MariaDB 官方yum源里面只有目前在维护的版本,而有时候对于老项目来说还是需要老版本的rpm包,国内很多镜像站都是同步的官方仓库,因此下载老版本也不好找,这里主要记录下从哪里可以下载到历史版本的MariaDB rpm包。 1. 官方归档网…...
Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件
一.类的介绍 1.QPdfWriter介绍 Qt中提供了一个直接可以处理PDF的类,这就是QPdfWriter类。 (1)PDF文件生成 支持创建新的PDF文件或覆盖已有文件,通过构造函数直接绑定文件路径或QFile对象; 默认生成矢量图形PDF&#…...
使用 Promptic 进行对话管理需要具备python技术中的那些编程能力?
使用 Promptic 进行对话管理时,需要掌握一些基础的编程知识和技能,以下是详细说明: 1. Python 编程基础 Promptic 是一个基于 Python 的开发框架,因此需要具备一定的 Python 编程能力,包括: 函数定义与使用:了解如何定义函数、使用参数和返回值。类型注解:熟悉 Python…...
