跳至主要内容

RDocumentation:评分与排序

了解 RDocumentation 的搜索结果是如何生成的!
Ludovic Vannoorenberghe
Ludovic Vannoorenberghe

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续继续即表示您接受我们的 使用条款,我们的 隐私政策 ,并且您的数据存储在美国。

RDocumentation.org 的核心功能之一是搜索。从一开始,我们就希望提供一个极其简单的搜索栏,无需在复杂的表单中填写包名、函数名、版本或其他信息。只要一个简单的搜索栏即可。

在今天的技术博客中,我们将重点介绍用于为用户提供相关且有意义结果的技术与方法。

Elasticsearch

RDocumentation.org 使用 Elasticsearch 来索引并搜索所有 R 包与主题。

Elasticsearch 是一个开源、可扩展、分布式、企业级的搜索引擎。

Elasticsearch 非常适合查询文档,因为它不使用传统的 SQL 数据,而是将文档存储为类似 JSON 的数据结构。每个文档只是由一些简单数据类型(字符串、数字、列表、日期等)的键-值对组成。其分布式特性意味着 Elasticsearch 可以非常快。

一个 Elasticsearch 集群可以拥有多个索引,每个索引可以包含多种文档类型。文档类型用于描述文档的结构。要了解更多关于 Elasticsearch 类型的信息,您可以访问elastic.co 上的指南。

RDocumentation.org 使用三种不同的类型:package_version、topic 和 package。前两种是主要类型;我们稍后再讨论 package。

由于 RDocumentation.org 是开源的,您可以在我们的GitHub 仓库中查看 Elasticsearch 的映射。

package_version 类型

package_version 类型类似于包的 DESCRIPTION 文件的翻译,包含其中的主要字段:package_name、version、title、description、release_date、license、url、copyright、created_at、updated_at、latest_version、maintainer 和 collaborators。maintainer 和 collaborators 字段是从 DESCRIPTION 文件中的 Authors 字段提取的。

topic 类型

主题文档从 R 中的标准文档格式 Rd 文件解析而来。topic 类型包含以下键:name、title、description、usage、details、value、references、note、author、seealso、examples、created_at、updated_at、sections、aliases 和 keywords。

Elasticsearch 中的评分

在进行任何评分之前,Elasticsearch 首先会通过检查文档是否与查询匹配来缩小候选集合。基本上,查询是一个词(或一组词)。根据查询设置,Elasticsearch 会在特定类型的特定字段中查找匹配。

然而,匹配并不一定意味着文档是相关的;同一个词在不同语境下可能有不同含义。基于查询设置,我们可以按类型和字段进行筛选,并加入更多上下文信息。这些上下文信息会提升相关性,而这正是评分发挥作用的地方。

Elasticsearch 底层使用 Lucene,因此评分基于 Lucene 的实用评分函数,它综合了TF-IDF、向量空间模型和布尔模型等模型来为文档评分。

如果您想进一步了解该函数在 Elasticsearch 中如何使用,可以查看elastic.co 指南的这一部分。

提升相关性的一种方法是对某些字段施加权重。例如,在 RDocumentation.org 的全站搜索中,我们会自然地提升包的 package_name 和 title 字段,以及主题的 aliases 和 name 字段。

另一种有效提升相关性的方法是根据热门程度为文档加权。其背后的想法是:如果某个包更受欢迎,用户更可能在搜索它。优先展示更受欢迎的包,将更可能让我们呈现出用户真正想要的结果。

用下载量衡量热度

衡量热门程度有多种方法。我们可以使用用户给出的直接指标,如投票或排名(类似亚马逊商品评分);也可以使用间接指标,如售出数量或观看次数(如 YouTube 视频)。

在 RDocumentation.org,我们选择了后者。更具体地说,我们使用下载次数作为热门程度的度量。间接指标通常更容易收集,因为它们不需要用户主动输入。

时间范围

使用下载次数时会产生一个问题:旧包的累计下载量自然比新包多。但这并不意味着它们更受欢迎,只是它们存在的时间更长。如果一个包多年前非常流行,但现在已过时且不再被社区积极使用,该怎么办?

为了解决这个问题,我们只考虑最近一个月的下载次数。这样一来,旧包的热门分不会被人为抬高,而过时的包会很快淡出。

直接下载与间接下载

反向依赖也会带来问题。R 包通常依赖于许多其他包。具有大量反向依赖的包会被下载得更多。然而,这些包通常更加底层,并不会被终端用户直接使用。我们必须注意不要让它们的下载数权重过高。

例如,看看 Rcpp。在 CRAN(Comprehensive R Archive Network,R 综合归档网络)上,超过 70% 的包依赖于它,这显然使其成为下载量最高的 R 包。然而,直接使用这个包并搜索其文档的 R 用户相对并不多。

为了解决这个问题,我们需要区分直接下载(由用户请求触发的下载)和间接下载(由于下载了依赖包而发生的下载)。为了从 CRAN 日志中区分直接与间接下载,我们采用了 Arun Srinivasan 在 cran.stats 包中描述的相同启发式方法。

现在我们有了一个有意义的热门度量:最近一个月的直接下载次数。Elasticsearch 提供了便捷的方式来注入这些附加信息;更多详情请参阅elastic.co 上的这篇文章。

评分的修改如下:

new_score = old_score * log(1 + number of direct downloads in the last month)

我们使用 log() 函数来平滑 下载次数 的取值,因为每一次新增下载的权重应当递减;0 与 1000 次下载之间的差异,对热门分的影响应大于 100,000 与 101,000 次之间的差异。

这种重新评分提升了 RDocumentation.org 搜索结果的整体相关性,因此用户可以将更多精力放在阅读文档上,而不是搜寻文档。

如果您想了解 Elasticsearch 查询的具体实现方式,可以查看 GitHub 上的 RDocumentation 项目。查询本身位于 SearchController 中。

如果您想进一步了解 RDocumentation.org 的实现方式,请查看我们的仓库:



关于 RDocumentation 

RDocumentation 汇聚了来自 CRAN、BioConductor 和 GitHub 的 R 包帮助文档——这三者是当前 R 文档最常见的来源。然而,RDocumentation.org 不止于简单聚合,它还通过 RDocumentation 包将所有文档呈现在您指尖。RDocumentation 包会覆盖 utils 包中的基础帮助函数,让您在熟悉的 RStudio IDE 中访问 RDocumentation.org。查找最新与最受欢迎的 R 包,检索文档并发布社区示例。

主题