作为一名 Rails 和 Ruby 爱好者,我经常搜索能完美满足我的使用场景的 gem。当我需要解决问题时,我希望选择 正确 的、最适合的解决方案。

Ruby gems 是 Ruby 社区内部创建的大量库。查找任何任务的现成解决方案的最佳位置是网站 rubygems.org,这是一个公共 gem 仓库,可以通过主页上的搜索框进行搜索。RubyGems 网站是一个高效的工具,它促进了软件包的共享和安装。但是,尽管它的搜索栏非常有用,但我还是决定创建一个 替代搜索栏,更适合我们的需求。

边输入边搜索的体验

首先,我想实现边输入边搜索的体验。这意味着

  • 响应时间低于 50 毫秒
  • 在用户键入时,立即在搜索框下方显示所有匹配结果,而无需用户按 Enter 键

在 RubyGems 网站中,由于每次请求都会加载一个新页面,因此目前还没有实现这种功能。

相关性

您可以使用 RubyGems 搜索栏获取相关且准确的结果,但大多数情况下只能通过执行高级搜索才能实现,而这并不总是方便。您必须决定要填写哪些部分。您是要通过输入名称来搜索特定的软件包(例如“devise”),还是找到摘要与关键字匹配的软件包(例如“部署”)?

但是,即使有这种功能,您也可能找不到满足您需求的 gem。例如,如果您输入“分页”,您可能希望看到 gem“kaminari”,它是 RoR 社区中最流行的分页 gem,出现在结果中。这是我们从 RubyGem 搜索栏提交关键字“分页”后得到的 返回结果。如您所见,“kaminari” 在第 9 个结果之前没有出现。

即使我们 细化搜索,显示的第一个结果仍然是“kanimari-core”,它并不是我们想要找到的更合适的、更著名的“kaminari” 软件包,但总比没有好。

然后,如果我们进行一个 包含请求中拼写错误的搜索,例如“pagintion”,页面将显示没有任何结果,并建议您在下次搜索时使用类似的词。

经过这段作为用户的体验后,我旨在创建一个能够 理解您想要什么并立即找到它单一搜索栏

Meilisearch 涵盖了所有这些要点,甚至更多!

我从未实现过搜索引擎;我甚至从未使用过,除了一个没有配置的基本 Elasticsearch 实例,用于概念验证。为此,我只需要一个易于设置的工具,能够同时处理速度和相关性。这就是 Meilisearch 非常适合这个项目的原因。

Meilisearch 是一个非常相关且快速的搜索引擎。换句话说,它可以在 50 毫秒内返回数据集中最相关的结果,因此它给人一种强烈的即时感。

此外,无需进行任何配置,它可以处理搜索拼写错误:即拼写错误。尝试提交“devose”而不是“devise”,Meilisearch 会将“devise”作为第一个结果返回。

最后,Meilisearch 是开源的,并集成了一个简单的 RESTful API。您可以使用 cURL 或 Meilisearch 的包装器之一 无缝地与 API 通信。

所有 gem 数据 都可以在 RubyGems 网站上作为 PostgreSQL 转储文件获得,并且每天更新。因此,我编写了一个 Ruby 脚本,用于下载最新的数据集、解析 PostgreSQL 转储文件并将所有数据推送到我的 Meilisearch 实例中。当然,它使用 meilisearch-ruby 包装器 与 API 通信。该脚本托管在 Heroku 中,并且由于 Heroku Scheduler 的功能,它每天都会运行。

关于 Meilisearch 实例,在 Meili,我们管理一个内部 Kubernetes 集群,这是一个用于托管类似演示的方便工具。对于想要了解更多信息的好奇的读者,Meilisearch 非常 易于下载和运行(Homebrew、APT、Docker…)。

关于 HTML 和 CSS,我保留了 RubyGems 网站的大部分原始结构。我的目的是以与原始网站相同的精神开发“边输入边搜索的体验”。前端使用 GitHub Pages 部署。

轻松提高相关性

无需进行任何设置,Meilisearch 就会返回相当相关的结果。我们的搜索引擎可以快速找到最合适的软件包,例如输入 gem 名称“devise”或“faraday”。不幸的是,目前关键字并非总是如此。

让我们回到我的“分页”示例。如果我在没有进行任何配置的情况下再次运行搜索,Meilisearch 将显示的第一个结果将是 Pagination gem。我在结果中完全看不到 Kaminari。这是因为默认情况下,在标题中找到一个请求词的文档优先于在描述中找到一个请求词的文档。由于数据集中有许多 gem 在标题中包含“分页”,因此可以解释为什么 Kaminari 根本没有出现。

我需要 Meilisearch 也包含库的流行度。在我的数据集中,Ruby gem 的流行度由下载次数表示。我将 gem 分为八个知名度组(下载次数超过 5000 万次、超过 3000 万次,依此类推),从 07。后者被认为是最知名的组。

我将此信息作为名为 fame 的字段添加到每个文档(即 gem)中。然后,我将此规则集成到 Meilisearch 设置中,作为自定义排名规则。

请看一下上面的代码片段。简单地说,Meilisearch 将逐一执行所有这些规则(_sum_of_typos_number_of_words…)并按照此顺序对您的文档进行排序。当我将我的自定义规则添加到 rankingOrder 中(即 fame)并在 rankingRules 中添加 fame: 'dsc' 时,实际上我是在要求 Meilisearch 按知名度降序排序。

您可能已经注意到示例中有一个第二个自定义规则:total_downloads,这样我的结果将按下载次数排序。但由于我选择将此规则放在列表的最后,这意味着它比其他规则不那么重要,因此它将是最后应用的规则。顺序很重要。

我不会详细介绍 Meilisearch 默认排名规则,即使它是一个特别有趣的话题。描述我们的搜索引擎是如何工作的确实应该单独写一篇文章!😉 剧透:Meilisearch 使用桶排序!

现在,如果您输入 像“分页”这样的全局关键字,您会发现 Kaminari 位于第一位;如果您再次尝试使用 例如像“pagy”这样的不太知名的 gem 名称,您仍然会得到您期望的 gem!🎉

Meilisearch + 您 = 💛

这些微小的设置非常容易集成,您的项目可能需要相同类型的行为。

如果您想为自己的 Meilisearch 体验做好准备,以下是一些有用的链接

如果您对我们的项目、其工作原理感兴趣,或者有任何反馈,请随时 联系团队!😁