Drupal 8:使用搜索 API 和 Solr 搜索提升日期搜索

Search API Solr 搜索模块有一堆用于提升某些字段的控件。这允许您为标题赋予更多权重(即提升),而为正文赋予更少权重,这意味着当搜索词出现在页面标题中时,它比仅在正文中包含该词的页面具有更大的权重. 这个权重值最终用于计算页面的分数,这直接影响结果的排序。

需要做更多工作的一件事是日期加权的概念。假设您想根据页面发布的时间来控制日期字段的提升,以便较新的页面获得更大的分数,从而在搜索结果中出现更高的位置。Search API Solr 模块中没有控件来处理此问题,因此我们需要创建一些自定义代码来完成此操作。值得庆幸的是,Solr 在这里工作的方式是搜索查询包含提升,而不是索引,因此我们需要做的就是改变查询以更改提升因子。您无需重新索引整个站点即可更新提升。

我们在这里需要的钩子是hook_search_api_solr_query_alter(),创建一个名为 boost_search 的模块,我们将创建一个看起来像这样的模块文件。

<?php
 
use Solarium\QueryType\Select\Query\Query;
use Drupal\search_api\Query\QueryInterface;
 
/**
 * Implements hook_search_api_solr_query_alter().
 */
function boost_search_search_api_solr_query_alter(Query $solarium_query, QueryInterface $query) {
  // 实现这一点。
}

如果您将 Solr 配置为与 Drupal 一起使用一段时间,那么您将意识到 Solr 会将您提供的字段转换为基于它们的基数和数据类型具有不同的名称。出于这个原因,并不总是可以“获取”该字段,因此我们首先需要询问搜索索引该字段在 Sorl 服务器中被称为什么。一旦我们有了这个,我们就可以看看如何创建提升。

function boost_search_search_api_solr_query_alter(Query $solarium_query, QueryInterface $query) {
  $index = $query->getIndex();
  $fields = $index->getServerInstance()
    ->getBackend()
    ->getSolrFieldNames($index);
  $solrField = !empty($fields[$dateField]) ? $fields[$dateField] : '';
 
}

可以使用该addParam()方法为搜索查询添加提升。第一个参数是bf,它为查询添加了 boost 函数,第二个参数详细说明了我们要应用的 boost 函数。Boost 函数将用于构造函数查询,这些查询将作为影响分数的可选子句添加到用户的主查询中。函数查询使您能够使用一个或多个数字字段的实际值生成相关性分数。Solr 本身支持的任何函数都可以在 bf 字段中使用,以及一个 boost 值。

$solarium_query->addParam('bf', "... boost ...");

要根据页面发布的时间创建提升,我们需要使用recip(x,m,a,b)Solr 函数。这是一个实现f(x)= a/(m*x+b)的倒数函数,其中 m、a 和 b 是常数,x 是任何数字字段。

$solarium_query->addParam('bf', "recip(abs(ms(NOW,{$solrField})),3.16e-11,10,0.1)");

让我们依次分解这个 boost 函数的每个部分。分解recip(x,m,a,b)函数我们得到以下部分。

x = abs(ms(NOW, {$solrField))

这实质上意味着我们想要显示当前时间和我们在 boost.xml 中规定的字段中的日期之间的差异(以毫秒为单位)。通过这abs()意味着它会自动转换为正数。

m = 3.16e-11

m 是一个常数,它定义了用于应用提升的时间刻度。它与我们认为的“旧”文档有关,并且
是以毫秒为单位的文档的逆年龄(因此是 -11)。目前设置为 3.16e-11,这意味着我们文章提升的截止点大约是 1 年。我们可以使用公式 1/(毫秒) 计算出不同的数量,因此如果您希望该值为 6 个月,那么它将是 6.3411541e-11,对于 3 个月,这将是 1.2683917e-10。

a = 10
b = 0.1

最后两个值是影响函数曲线的常数。较低的值意味着线快速下降,每个值为 1 意味着非常浅的线,不会提供太多提升并且缓慢向下。上面使用的值创建了一个积极的向下曲线。

为了更好地展示不同的值对 boost 函数的影响,我使用 m 因子的相同值 3.16e-11 绘制了一些值。

A - a=10 b=0.1
B - a=1 b=1
C - a=1 b=0.1
D - a=50 b=10

从这个例子中可以看出,所有的值都会产生一条曲线。Y 轴代表分数,X 轴代表时间。改变 a 和 b 中的值会导致曲线改变形状,但较大的值会导致更浅的曲线。这表明,如果您使用 a=10 和 b=0.1(上图中的 A),那么最近的文章将在搜索结果中获得巨大的提升,而使用 a=1 和 b=1 (B) 会获得非常小的搜索结果提升到最近的文章。

将所有这些放在一起,我们得到以下内容。

<?php
 
use Solarium\QueryType\Select\Query\Query;
use Drupal\search_api\Query\QueryInterface;
 
/**
 * Implements hook_search_api_solr_query_alter().
 */
function boost_search_search_api_solr_query_alter(Query $solarium_query, QueryInterface $query) {
  $dateField = 'created';
  $index = $query->getIndex();
  $fields = $index->getServerInstance()
    ->getBackend()
    ->getSolrFieldNames($index);
  $solrField = !empty($fields[$dateField]) ? $fields[$dateField] : '';
 
  if ($solrField) {
      $solarium_query->addParam('bf', "recip(abs(ms(NOW,{$solrField})),3.16e-11,10,0.1)");
    }
  }
}

此处使用的值将对最近的文章产生很大的推动作用。您应该尝试使用不同的 a 和 b 值,看看它们如何改变您的搜索结果。

您可以做的另一件事是将recip()函数包装在一个min()函数中。这意味着您的最小提升不会低于 0.5 或您设置的任何值。如果您发现旧的和相关的文章没有得到足够的提升,这会很方便。我在这方面取得的成功有限,但我将其添加到此处,以防您发现它有用。

$solarium_query->addParam('bf', "min(recip(abs(ms(NOW,{$solrField})),3.16e-11,10,0.1), 0.5)");