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 包,检索文档并发布社区示例。

RDocumentation.org 的核心功能之一是搜索。从一开始,我们就希望提供一个极其简单的搜索栏,无需在复杂的表单中填写包名、函数名、版本或其他信息。只要一个简单的搜索栏即可。
在今天的技术博客中,我们将重点介绍用于为用户提供相关且有意义结果的技术与方法。
Elasticsearch
RDocumentation.org 使用 Elasticsearch 来索引并搜索所有 R 包与主题。
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 上的这篇文章。
评分的修改如下:
我们使用
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 包,检索文档并发布社区示例。