
今天,我将带领大家深入探索crates.io,以及我是如何利用我们的即时搜索引擎:Meilisearch,制作一个替代的搜索栏。
Meili 即时、相关、容错的搜索引擎
Crates.io 是存储 Rust 社区 crate(包)的官方网站,也是 cargo 包管理器上传、更新和下载这些包的地方。
Sean Griffin 是 crates.io 团队的一员,负责维护其当前的搜索引擎以及整个网站。Kornel Lesinski 构建了 lib.rs,作为 crates.io 的替代品,并使用 Tantivy 来为其搜索栏提供支持。说实话,我更喜欢它的颜色设计,这就是为什么我将它用于我们的搜索演示。
我决定运行我们的即时搜索引擎,并针对这些现有解决方案测试其随时间变化的相关性。我们的搜索引擎使用完全不同的算法;它基于前缀搜索,并具有容错能力。
Meili 具有容错能力并支持大量其他功能
所以,我问自己:为什么不使用我们新的即时搜索引擎,并让它对我们亲爱的社区有用呢?这会给我们带来很多反馈,并在此过程中可能会收到一些拉取请求。
在 Meili,我们管理着一个内部 Kubernetes 集群,这对于为客户托管演示很有用。此演示的 Meilisearch 服务器目前在该集群中的一个 Pod 上运行。
为了让 Meilisearch 展示这些 crate,我们需要找到 crates.io 上所有当前可用的包。幸运的是,这个索引在 GitHub 上以几个子文件夹的形式提供,其中包含包的名称和版本,大约有 *32,000* 个文件。每次 crate 更新到新版本或某个版本被撤回时,都会进行一次提交。
因此,我使用了 crates.io-index 仓库来**初始化**我们新创建的 Meili 搜索引擎,但首先需要更多数据,例如每个 crate 的描述、关键词和类别。再次,Rust crates.io 团队为我们提供了帮助,我与 Pietro Albini 进行了交谈,他向我指出了提供包内容且不受速率限制的服务器。
现在我们可以检索到有用的数据了,我创建了一个异步爬虫,它下载、解压、检索 Cargo.toml,并将基本数据上传到 Meilisearch。
Meili 仪表板界面显示原始文档
Meilisearch 现在可以理解这些数据,并为我们提供即时、相关且容错的响应。但是,新的 crate 呢?我们希望收到新 crate 的通知,并能够将它们发送到 Meilisearch。
Docs.rs 是官方网站,用于计算和存储所有由 crates.io 托管的 Rust 包的文档。它每分钟都会比对 crates.io 索引,以了解新的 crate 更新。幸运的是,它提供了这些更新的 Atom feed。
这就是 Heroku 发挥作用的地方。Heroku 每月提供大约 *1000* 小时的免费服务器计算能力,并为我们提供调度器。我们可以利用这些积分,每 10 分钟免费向 docs.rs 询问新更新的 crates,通过获取 Atom feed,像以前一样下载更新的包,最后**实时**更新我们的搜索引擎!
获取新的 crates 需要4秒
搜索结果令人满意,但未达到预期,有些不对劲。例如,当我们输入“serde”时,第一个结果是相关的,但接下来的结果却不相关。这与 Meilisearch 除了查询匹配词之外没有足够的数据来对 crate 进行评分有关。
Meilisearch 仅凭匹配词无法区分同等重要的 crates
**下载量**显著改善了搜索结果。此数据可通过 crates.io 获取。每天都会进行一次完整的数据库导出,其中包含每个 crate 的下载次数。我决定将这些数据作为最后的排序标准,以帮助 Meilisearch 确定哪些 crate 被认为是同等重要的。
得益于下载量,Meilisearch 显示了更好的结果
我部署了一个 Heroku 调度器,每天运行一次以更新所有 crate 的下载量;下载 tarball、解压、读取 CSV 并将 *32,000* 个 crate 的下载量上传到 Meilisearch 大约需要 30 秒。因此,我们远远没有用完每月 *1000* 小时的免费时间。
我认为这个搜索演示非常不错,但我也考虑过添加同义词和停用词,因为 Meilisearch 支持这些功能。例如,输入“db”就能看到与“database”相关的结果会很方便。停用词将有助于忽略“the”或“that”等无用词,这些词有时会污染搜索结果,但我们需要小心,因为 crate 名称可能由停用词组成。
Meilisearch 还支持基本过滤,未来能够按类别或特定关键词搜索 crates 将会非常棒。
所有这些改进都可以由您来完成;演示是开源的。核心引擎源代码也在 GitHub 上提供,这就是本文的重点!看一看并讨论它,参与的人越多,功能就越多!