结果聚类

在版本 9.0 中,集群组件实现和 API(参数)发生了重大更改。请参阅与 Solr 版本完全匹配的 Solr 指南版本。

集群(或群集分析)插件尝试自动发现相关搜索结果(文档)组,并为这些组分配人类可读的标签。

Solr 中的集群算法应用于每个单个查询的搜索结果中包含的文档——这称为在线集群。

为给定查询发现的集群可以被视为动态分类。当常规分类困难(字段值事先未知)或查询本质上是探索性的时,这很有用。查看 Carrot2 项目的演示页面,了解搜索结果集群操作的示例(可视化中的组已在右侧的搜索结果中自动发现,没有涉及外部信息)。

image

发送给系统的查询是Apache Solr。很明显,分类无法产生类似的组,尽管这两种技术的目标相似——让用户探索搜索结果集,并重新表述查询或将重点缩小到当前文档的子集。集群也类似于 结果分组,因为它可以帮助更深入地查看搜索结果,而不仅仅是前几个结果。

模块

这通过 clustering Solr 模块 提供,在使用前需要启用该模块。

配置快速入门

聚类扩展作为搜索组件工作。它需要在 solrconfig.xml 中声明和配置,例如

<searchComponent class="org.apache.solr.handler.clustering.ClusteringComponent" name="clustering">
  <lst name="engine">
    <str name="name">lingo</str>
    <str name="clustering.fields">title, content</str>
    <str name="clustering.algorithm">Lingo</str>
  </lst>
</searchComponent>

上述声明了具有单个 引擎的聚类组件——可以在运行时声明和切换多个引擎。我们稍后将返回有关如何配置引擎的详细信息。

聚类组件必须附加到 SearchHandler 并通过属性 clustering 显式启用。将其附加为处理程序管道中的最后一个组件非常重要,如下所示

  <requestHandler name="/select" class="solr.SearchHandler">
    <lst name="defaults">
      <bool name="clustering">true</bool>
      <str name="clustering.engine">lingo</str>
    </lst>

    <arr name="last-components">
      <str>clustering</str>
    </arr>
  </requestHandler>

一旦附加,如上例所示,聚类将自动对与搜索处理程序查询匹配的所有文档执行。聚类扩展将考虑引擎的 clustering.fields 参数中列出的所有文本字段,并将生成响应的部分,称为 clusters,其中包含发现的组结构,例如(为简洁起见,JSON 响应)

{
    "clusters": [
        {
          "labels": ["Memory"],
          "score": 6.80,
          "docs":[ "0579B002",
            "EN7800GTX/2DHTV/256M",
            "TWINX2048-3200PRO",
            "VDBDB1A16",
            "VS1GB400C3"]},
        {
          "labels":["Coins and Notes"],
          "score":28.560285143284457,
          "docs":["EUR",
            "GBP",
            "NOK",
            "USD"]},
        {
          "labels":["TFT LCD"],
          "score":15.355729924203429,
          "docs":["3007WFP",
            "9885A004",
            "MA147LL/A",
            "VA902B"]}
    ]
}

每个群集的 labels 元素是一个动态发现的短语,用于描述和应用于 docs 元素下的所有文档标识符。

Solr 分发示例

Solr 附带的“techproducts”示例预先配置了结果聚类所需的所有组件——但它们默认情况下处于禁用状态。

要启用聚类组件扩展和配置为使用它的专用搜索处理程序,请在运行示例时指定一个 JVM 系统属性

bin/solr start -e techproducts -Dsolr.clustering.enabled=true

您现在可以通过在浏览器中打开以下 URL 来试用聚类处理程序

http://localhost:8983/solr/techproducts/clustering?q=*:*&rows=100&wt=xml

输出 XML 应包括搜索结果和自动发现的群集数组,类似于此处显示的输出

<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">299</int>
  </lst>
  <result name="response" numFound="32" start="0" maxScore="1.0">
    <doc>
      <str name="id">GB18030TEST</str>
      <str name="name">Test with some GB18030 encoded characters</str>
      <arr name="features">
        <str>No accents here</str>
        <str>这是一个功能</str>
        <str>This is a feature (translated)</str>
        <str>这份文件是很有光泽</str>
        <str>This document is very shiny (translated)</str>
      </arr>
      <float name="price">0.0</float>
      <str name="price_c">0,USD</str>
      <bool name="inStock">true</bool>
      <long name="_version_">1448955395025403904</long>
      <float name="score">1.0</float>
    </doc>

    <!-- more search hits, omitted -->
  </result>

  <arr name="clusters">
    <lst>
      <arr name="labels">
        <str>DDR</str>
      </arr>
      <double name="score">3.9599865057283354</double>
      <arr name="docs">
        <str>TWINX2048-3200PRO</str>
        <str>VS1GB400C3</str>
        <str>VDBDB1A16</str>
      </arr>
    </lst>
    <lst>
      <arr name="labels">
        <str>iPod</str>
      </arr>
      <double name="score">11.959228467119022</double>
      <arr name="docs">
        <str>F8V7067-APL-KIT</str>
        <str>IW-02</str>
        <str>MA147LL/A</str>
      </arr>
    </lst>

    <!-- More clusters here, omitted. -->

    <lst>
      <arr name="labels">
        <str>Other Topics</str>
      </arr>
      <double name="score">0.0</double>
      <bool name="other-topics">true</bool>
      <arr name="docs">
        <str>adata</str>
        <str>apple</str>
        <str>asus</str>
        <str>ati</str>
        <!-- other unassigned document IDs here -->
      </arr>
    </lst>
  </arr>
</response>

针对此查询(*:*)发现的几个群集将所有搜索结果分成不同的类别:DDR、iPod、硬盘等。每个群集都有一个标签和分数,表示群集的“优劣”。分数是特定于算法的,并且仅相对于同一集合中其他群集的分数才有意义。换句话说,如果群集 A 的分数高于群集 B,则群集 A 的质量应该更好(具有更好的标签和/或更连贯的文档集)。每个群集都有一个属于它的文档标识符数组。这些标识符对应于模式中声明的 uniqueKey 字段。

有时群集标签可能没有多大意义(这取决于许多因素——聚类字段中的文本、文档数量、算法参数)。此外,某些文档可能会被遗漏并且根本不会被聚类;这些文档将被分配到合成的 其他主题 组,并标记为 other-topics 属性设置为 true(请参阅上面的 XML 转储以获取示例)。其他主题组的分数为零。

配置

组件配置

以下属性控制 ClusteringComponent 状态。

clustering

可选

默认值:false

即使正确声明并附加到搜索处理程序,该组件默认情况下也是禁用的。必须将 clustering 属性设置为 true 才能启用它。这可以通过在搜索处理程序中设置默认参数来完成,如下一节所述。

clustering.engine

可选

默认值:参见说明

声明要使用的引擎。如果不存在,则使用声明的第一个活动引擎。

聚类引擎

solrconfig.xml 中的聚类组件声明必须包含一个或多个称为引擎的预定义配置。例如,考虑以下配置

<searchComponent class="org.apache.solr.handler.clustering.ClusteringComponent" name="clustering">
  <lst name="engine">
      <str name="name">lingo</str>
      <str name="clustering.algorithm">Lingo</str>
      <str name="clustering.fields">title, content</str>
  </lst>

  <lst name="engine">
      <str name="name">stc</str>
      <str name="clustering.algorithm">STC</str>
      <str name="clustering.fields">title</str>
  </lst>
</searchComponent>

这声明了两个单独的引擎(lingostc):这些配置具有不同的聚类算法和不同的聚类文档字段集。可以通过在运行时(通过 URL)传递 clustering.engine=name 参数或作为搜索处理程序配置中的默认值来选择活动引擎,如下所示

<requestHandler name="/clustering" class="solr.SearchHandler">
  <lst name="defaults">
    <!-- Clustering component enabled. -->
    <bool name="clustering">true</bool>
    <str name="clustering.engine">stc</str>

    <!-- Cluster the top 100 search results - bump up the 'rows' parameter. -->
    <str name="rows">100</str>
  </lst>

  <!-- Append clustering at the end of the list of search components. -->
  <arr name="last-components">
    <str>clustering</str>
  </arr>
</requestHandler>

聚类引擎配置参数

每个声明的引擎都可以使用下面描述的多个参数进行配置。

clustering.fields

必需

默认值:无

应包含用于聚类的文本内容的文本字段的逗号(或空格)分隔列表。必须提供至少一个字段。这些字段与搜索处理程序的 fl 参数分开,以便聚类字段不必包含在响应中。

clustering.algorithm

必需

默认值:无

聚类算法是发现文档之间关系并形成人类可读的聚类标签的实际逻辑(实现)。此参数设置此引擎将使用的聚类算法的名称。算法通过 Carrot2 定义的服务扩展提供给 Solr。默认情况下,应提供以下开源算法:LingoSTCBisecting K-Means。商业聚类算法 Lingo3G 插入到同一扩展点,如果在类路径上可用,则可以使用它。

如何选择聚类算法?

选择哪种算法取决于流量、预期结果和输入数据(每种算法对输入的聚类方式略有不同)。没有一种算法可以回答“哪种算法是‘最佳’算法”:Lingo3G 提供分层聚类,Lingo 和 STC 提供平面聚类。STC 比 Lingo 更快,但产生的聚类可能不太直观,Lingo3G 是最快的算法,但不是免费或开源的……进行试验并选择一种适合您需求的算法。

有关这些算法特性的比较,请参阅以下链接

聚类组件在启动时列出所有可用的算法、语言和算法语言兼容性。您可以查看启动日志,了解 Solr 安装中有哪些可用项。

clustering.maxLabels

可选

默认值:无

返回的聚类标签的最大数量(如果算法返回更多标签,则列表将被截断)。默认情况下,将返回所有标签。

clustering.includeSubclusters

可选

默认值:无

如果为 true,则子聚类将包含在支持分层聚类的算法的响应中。false 导致仅返回顶级聚类。

clustering.includeOtherTopics

可选

默认值:true

如果为 true,则会形成一个名为其他主题的合成聚类,其中包含未分配给任何其他聚类的所有文档,并将其返回。如果不需要此合成聚类,则可以将其设置为 false

clustering.resources

可选

默认值:无

算法特定资源和配置文件(停用词、其他词法资源、默认设置)的位置。此属性默认情况下为 null,所有资源均从各自的算法默认资源池(JAR)中读取。如果此属性不为空,则相对于 Solr 核心配置目录进行解析。此参数适用于 Solr 启动期间,不能按请求覆盖。

还有更多适用于引擎配置的属性。我们将在后面的功能部分中对此进行描述。

全字段和查询上下文(摘要)聚类

聚类算法可以消耗字段的全部内容,也可以只消耗查询匹配区域周围的左右上下文(所谓的摘要)。与直觉相反,即使向算法提供的数据较少,使用查询上下文也可以提高聚类的质量。这通常是由于摘要更专注于围绕查询的短语和术语,并且算法具有更好的数据信噪比以供使用。

当字段包含大量内容时,我们建议使用查询上下文(这会影响聚类性能)。

以下三个属性控制处理上下文或全部内容以及如何为聚类形成摘要。

clustering.preferQueryContext

可选

默认值:无

如果为 true,引擎将尝试提取查询匹配区域周围的上下文,并将这些上下文用作聚类算法的输入。

clustering.contextSize

可选

默认值:无

上下文检索算法(内部高亮显示器)创建的每个片段的最大字符数。

clustering.contextCount

可选

默认值:无

单个字段中不同、不连续片段的最大数量。

默认聚类语言

Carrot2 中聚类算法的默认实现(随 Solr 提供)内置支持(词干提取、停用词)用于预处理多种语言。为聚类算法提供要用于聚类的语言提示非常重要。这可以通过两种方式完成——通过传递默认语言的名称或通过将语言作为每个文档的字段提供。以下两个引擎配置参数控制此操作

clustering.language

可选

默认值:英语

用于聚类的默认语言的名称。提供的语言必须可用,并且聚类算法必须支持它。

clustering.languageField

可选

默认值:无

存储文档语言的文档字段的名称。如果文档不存在该字段或值为空,则使用默认语言。

受支持语言的列表可能会动态更改(语言通过外部服务提供程序扩展加载),并且可能取决于所选算法(算法可以支持资源可用的语言子集)。聚类组件将在 Solr 启动时记录所有受支持的算法语言对,以便您可以检查在特定 Solr 实例上受支持的内容。例如

2020-10-29 [...] Clustering algorithm Lingo3G loaded with support for the following languages: Dutch, English
2020-10-29 [...] Clustering algorithm Lingo loaded with support for the following languages: Danish, Dutch, English, Finnish, French, German, Hungarian, Italian, Norwegian, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish
2020-10-29 [...] Clustering algorithm Bisecting K-Means loaded with support for the following languages: Danish, Dutch, English, Finnish, French, German, Hungarian, Italian, Norwegian, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish

处理多语言内容

索引(和查询结果)通常包含多种语言的文档。对这类搜索结果进行聚类存在问题。理想情况下,引擎应该翻译(或理解)文档的内容,然后将相关信息分组在一起,无论其书面语言如何。

实际上,聚类算法通常要简单得多——它们从出现在这些文档中的术语和短语的统计属性中推断文档之间的相似性。因此,用不同语言编写的文本聚类效果不会太好。

为了应对这种情况,Solr 中的默认聚类组件实现将尝试首先按语言对所有文档进行分组,然后对该语言中的每个子组应用聚类。建议将每篇文档的语言存储为其单独的字段,并使用上面描述的 clustering.languageField 配置属性指向它。

调整算法设置

Solr 附带的聚类算法使用其默认参数值和语言资源。我们强烈建议对生产用途进行调整。改进默认语言资源以包含特定文档域中常见的单词和短语将显著提高聚类质量。

Carrot2 算法有一组广泛的参数和语言资源调整选项。请参阅 最新的项目文档。特别是语言资源部分和每个算法的属性部分。

更改聚类算法参数

聚类算法设置可以通过 Solr 参数进行更改,无论是永久的(在引擎声明中)还是按请求(通过 Solr URL 参数)。

例如,让我们假设以下引擎配置

<lst name="engine">
  <str name="name">lingo</str>
  <str name="clustering.algorithm">Lingo</str>
  <str name="clustering.fields">name, features</str>
  <str name="clustering.language">English</str>
</lst>

首先,在 Carrot2 文档站点 上找到 Lingo 算法的配置参数

image

然后找到您想要更改的特定设置,并记下该设置的 REST API 路径(在本例中,参数是 minClusterSize,其路径是 preprocessing.documentAssigner.minClusterSize

image

现在将完整路径值对添加到引擎的配置中

<lst name="engine">
  <str name="name">lingo</str>
  <str name="clustering.algorithm">Lingo</str>
  <str name="clustering.fields">name, features</str>
  <str name="clustering.language">English</str>

  <int name="preprocessing.documentAssigner.minClusterSize">3</int>
</lst>

以下规则适用。

自定义语言资源

聚类算法依赖于语言和特定领域的语言资源来提高集群的质量(通过丢弃特定领域的噪音和样板语言)。

默认情况下,语言资源是从引擎声明的算法默认 JAR 中读取的。您可以通过指定 clustering.resources 参数来传递这些资源的自定义位置。此参数的值解析为相对于 Solr 内核配置目录的位置。例如,以下定义

<lst name="engine">
  <str name="name">lingo</str>
  <str name="clustering.algorithm">Lingo</str>
  <str name="clustering.fields">name, features</str>
  <str name="clustering.language">English</str>

  <str name="clustering.resources">lingo-resources</str>
</lst>

将导致以下日志条目和预期的资源位置

Clustering algorithm resources first looked up relative to: [.../example/techproducts/solr/techproducts/conf/lingo-resources]

开始调整算法资源的最佳方法是从其相应的 Carrot2 JAR 文件(或 Carrot2 分发)中复制所有默认值。

性能注意事项

搜索结果的聚类会带来一些性能注意事项

  • 获取比平时更多的搜索结果(50、100 或更多文档)的成本,

  • 聚类本身的额外计算成本。

  • 在分布式模式下,用于聚类的文档字段的内容从分片中收集,并增加了一些额外的网络开销。

对于简单的查询,聚类时间通常会主导其他所有内容。如果文档字段很长,则存储内容的检索可能会成为瓶颈。

可以通过多种方式降低聚类的性能影响。

  • 聚类更少的数据:使用查询上下文(摘要)而不是完整字段内容(clustering.preferQueryContext=true)。

  • 仅对文档字段的子集执行聚类或整理用于聚类的字段(在索引时添加摘要)以减小输入。

  • 调整与特定算法直接相关的性能属性。

  • 尝试不同的、更快的算法(STC 而不是 Lingo,Lingo3G 而不是 STC)。

其他资源

以下资源提供了有关 Solr 中的聚类组件及其潜在应用的其他信息。