指南

如何为应用添加搜索:从简单筛选到全文搜索

要为应用添加搜索,先从最简单、可行的方案开始:一个搜索框调用服务端路由,该路由根据查询内容匹配几个字段来筛选数据库中的行,并提供分类或价格等筛选条件。如果这样还不够用,比如需要相关性排序、词干提取或数据量很大,就切换到数据库的全文搜索;只有在需要很强的容错拼写,或在超大数据上即时返回结果时,才考虑托管搜索引擎。无论选哪种方案,搜索都必须遵守权限规则:用户绝不应搜到他们无权查看的记录。

对你的应用而言,“搜索”意味着什么

搜索包含几种不同的功能,大多数应用需要的不止一种:

  • **关键词搜索:**一个文本框,例如“查找提到‘花园’的房源”。
  • **筛选:**结构化的选项,如分类、城市、价格区间、日期、状态。
  • **排序:**最新、最便宜、最相关。
  • **自动补全:**输入时给出建议。
  • 容错拼写:“restuarant”仍能找到“restaurant”。

对于目录、招聘网站或商店来说,筛选往往比文本框更重要。在选择工具之前,先确定你真正需要哪些功能。

你的选择

方式工作原理适用场景局限
在浏览器中筛选加载列表,用 JavaScript 过滤小型公开列表(几百条)所有数据都发送给每位访客;列表大时变慢
数据库模式匹配服务端查询“名称包含该文本”,不区分大小写中小型应用、管理后台无排序;大表上可能变慢;没有词干提取
数据库全文搜索Postgres 为单词建立索引并对匹配结果排序大多数内容密集型应用除非添加模糊匹配,否则对拼写错误的容错较弱
模糊匹配(三元组)Postgres 比较字符序列的相似度名称、短字段、容错拼写需要扩展和索引;需要调优
托管搜索引擎独立服务为你的数据建立索引(Algolia、Meilisearch、Typesense、Elasticsearch 等)大型目录、即时搜索、强容错拼写另一项需要同步、付费并保障安全的服务

如果你的数据已经在 Postgres 中,它内置的全文搜索是很好的折中方案。它会把文本拆分成单词,将单词还原为词干(因此“running”能匹配“run”),忽略常见词,并根据匹配程度对结果排序。配上合适的索引后,即使在大表上也能保持快速。

示例提示词

简单入门:

在房源列表页添加搜索框和筛选条件。搜索应在标题和描述中做不区分大小写的匹配。筛选条件:分类(下拉框)、城市(下拉框)和最高价格。搜索在服务端完成,使用分页的 API 路由,每页 20 条结果。将搜索和筛选条件保存在 URL 中,使结果可以分享,并且浏览器的后退按钮可以正常使用。没有匹配结果时,显示友好的空状态提示。

升级为全文搜索:

将房源搜索切换为 Postgres 全文搜索,对标题(权重更高)和描述进行索引。添加正确的索引,按相关性排序,并保留现有的筛选和分页功能。不要修改任何现有数据。

为名称添加容错拼写:

为企业名称添加模糊匹配,使小的拼写错误也能找到结果。如果可用,使用三元组相似度并建立索引;如果不可用,则回退到当前的搜索方式。

分步操作

  1. **列出用户会搜索什么。**需要搜索哪些字段(标题、描述、标签、名称)?有哪些筛选条件?如果可以,请询问几位真实用户。
  2. **从服务端开始。**添加一个 API 路由,接收查询内容和筛选条件,并返回一页结果。不要把所有数据加载到浏览器中。
  3. **在查询中应用权限。**如果用户只能看到自己的记录,或只能看到已发布的记录,这个条件应与搜索放在同一个查询中。
  4. **从一开始就加入分页。**可以使用页码,也可以使用“加载更多”。
  5. **将搜索状态放入 URL。**例如 ?q=garden&city=leeds。这样链接可以分享,后退按钮也能正常工作,如果希望搜索引擎抓取筛选后的页面,它们也能被抓取。
  6. **输入时对搜索做防抖处理。**停止输入后等待几百毫秒再发起查询,避免每次按键都发送一次请求。
  7. 在确定了要筛选和搜索的列之后,再添加索引。
  8. **逐步升级:**先全文搜索,再模糊匹配,最后才是托管搜索引擎,并且只有在较简单的方案无法满足真实用户需求时才升级。
  9. **用接近真实的数据进行测试:**数百或数千行数据、特殊字符、空查询、超长查询,以及如果你支持其他语言,也要测试这些语言的内容。

常见错误

  • **把整张表加载到浏览器中。**50 条数据时没问题,5 万条数据时就很痛苦,而且会暴露每一条记录,包括用户本不应看到的记录。
  • **搜索忽略权限。**搜索是常见的数据泄露点:查询中忘记加上“仅限本人”或“仅限已发布”的条件,导致私密或草稿记录出现在结果中。
  • **用原始用户输入拼接 SQL。**务必使用参数化查询。AI 构建工具通常会这样做,但如果你看到字符串被拼接在一起,请检查一下。
  • 没有空状态。“没有结果”并附上建议(清除筛选条件、检查拼写),能避免用户直接离开。
  • **没有索引。**用测试数据时搜索感觉正常,但随着真实数据增长会越来越慢。
  • **直接上搜索服务。**这样你就要维护第二份数据副本,处理删除操作,并保护另一组密钥,而且往往看不出有什么明显收益。
  • **忘记移动端。**筛选条件需要能在手机上显示;使用抽屉式或可折叠的筛选面板,通常比侧边栏更合适。

检查清单

  • 你知道哪些字段需要搜索,以及有哪些筛选条件
  • 搜索在服务端运行,并返回分页结果
  • 查询遵循应用其他部分相同的权限规则
  • 用户输入作为参数传递,绝不拼接进 SQL
  • 搜索状态保存在 URL 中
  • 输入过程已做防抖处理
  • 用于搜索和筛选的列已建立索引
  • 空状态、无结果状态和错误状态都清晰明确
  • 已用接近真实的数据量和杂乱的输入进行测试

在 Mythex 中添加搜索

在基于 Mythex 构建的应用中,数据通常存放在项目自己的 Postgres 数据库中,因此你可以直接使用上面的提示词:先做模式匹配,需要排序时再使用 Postgres 全文搜索。如果你想使用托管搜索引擎,请使用你自己的账户和密钥,将其保存为项目机密,并让代理在服务端完成索引和查询,具体步骤参见集成任意 API。

搜索是许多应用的核心:有关它如何融入整个产品,请参见如何搭建目录网站、如何搭建招聘网站和如何搭建市场平台。

常见问题

为应用添加搜索,最简单的方法是什么?

如果数据存放在数据库中,那么最容易上手的方法是:服务端路由对几个字段做不区分大小写的匹配,筛选出符合条件的行。如果是已经加载到浏览器里的小列表,直接在浏览器中筛选就更简单。

搜索一定要用 Algolia 或 Elasticsearch 吗?

一开始通常不需要。Postgres 全文搜索就能很好地处理单词匹配、排序,以及从几千到几百万行的数据。只有在需要很强的容错拼写、输入时即时显示结果(数据量很大时),或需要精细的相关性调优时,托管搜索引擎才值得使用。

为什么我的搜索在输入错字时找不到结果?

基础匹配和标准全文搜索查找的是原样输入的单词(或其词干),所以拼写错误就匹配不上。你需要模糊匹配,例如 Postgres 中的三元组相似度,或者支持容错拼写的搜索引擎。

搜索应该在浏览器中运行,还是在服务端运行?

除非是很小的公开列表,否则应放在服务端。服务端搜索可以扩展,能遵守权限规则,也不会把整个数据集发送给每位访客。

Mythex · Pricing · 用 AI 构建任何东西 · 网站和应用模板 · Mythex 对比 · AI 应用构建术语表 · 免费的 AI 应用构建工具 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 繁體中文(香港) 繁體中文(台灣)