分析器

分析器检查字段的文本并生成令牌流。

分析器在 Solr 的模式中被指定为 <fieldType> 元素的子元素。

在正常使用中,只有 solr.TextFieldsolr.SortableTextField 类型的字段会指定分析器。配置分析器最简单的方法是使用单个 <analyzer> 元素,其 class 属性是一个完全限定的 Java 类名。指定的类必须派生自 org.apache.lucene.analysis.Analyzer。例如

<fieldType name="nametext" class="solr.TextField">
  <analyzer class="org.apache.lucene.analysis.core.WhitespaceAnalyzer"/>
</fieldType>

在这种情况下,单个类 WhitespaceAnalyzer 负责分析指定文本字段的内容并发出相应的令牌。对于简单的用例,例如纯英文散文,像这样的单个分析器类可能就足够了。但通常需要对字段内容进行更复杂的分析。

即使是最复杂的分析要求,通常也可以分解为一系列离散的、相对简单的处理步骤。正如您很快将发现的那样,Solr 发行版附带大量分词器和过滤器,可以涵盖您可能遇到的大多数情况。设置分析器链非常简单;您指定一个简单的 <analyzer> 元素(没有 class 属性),其中包含子元素,这些子元素按您希望它们运行的顺序命名要使用的分词器和过滤器的工厂类。

例如

  • 使用名称

  • 使用类名(旧版)

<fieldType name="nametext" class="solr.TextField">
  <analyzer>
    <tokenizer name="standard"/>
    <filter name="lowercase"/>
    <filter name="stop"/>
    <filter name="englishPorter"/>
  </analyzer>
</fieldType>

分词器和过滤器工厂类通过它们的符号名称(SPI 名称)引用。此处,name="standard" 指的是 org.apache.lucene.analysis.standard.StandardTokenizerFactory

<fieldType name="nametext" class="solr.TextField">
  <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.StopFilterFactory"/>
    <filter class="solr.EnglishPorterFilterFactory"/>
  </analyzer>
</fieldType>

请注意,此处可以使用简写 solr. 前缀引用 org.apache.lucene.analysis 包中的类。

在这种情况下,没有在 <analyzer> 元素上指定 Analyzer 类。而是将一系列更专业的类连接在一起,并共同充当该字段的分析器。该字段的文本被传递给列表中的第一项(solr.StandardTokenizerFactory),并且从最后一项(solr.EnglishPorterFilterFactory)中出现的令牌是用于索引或查询任何使用 "nametext" fieldType 的字段的术语。

字段值与索引术语

分析器的输出会影响给定字段中索引的术语(以及在解析针对这些字段的查询时使用的术语),但它不会影响字段的存储值。例如:一个分析器可能会将“Brown Cow”拆分为两个索引术语“brown”和“cow”,但存储的值仍然是单个字符串:“Brown Cow”

分析阶段

分析在两种情况下进行。在索引时,当创建一个字段时,分析产生的令牌流会被添加到索引中,并定义该字段的术语集合(包括位置、大小等等)。在查询时,被搜索的值会进行分析,产生的结果术语会与存储在该字段索引中的术语进行匹配。

在许多情况下,应该对两个阶段应用相同的分析。当你想要查询精确的字符串匹配时,例如可能不区分大小写,这是理想的选择。在其他情况下,你可能希望在索引期间应用与查询时略有不同的分析步骤。

如果你为一个字段类型提供一个简单的 <analyzer> 定义,如上面的例子所示,那么它将用于索引和查询。如果你想为每个阶段使用不同的分析器,你可以包含两个带有类型属性区分的 <analyzer> 定义。例如

  • 使用名称

  • 使用类名(旧版)

<fieldType name="nametext" class="solr.TextField">
  <analyzer type="index">
    <tokenizer name="standard"/>
    <filter name="lowercase"/>
    <filter name="keepWord" words="keepwords.txt"/>
    <filter name="synonymFilter" synonyms="syns.txt"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer name="standard"/>
    <filter name="lowercase"/>
  </analyzer>
</fieldType>
<fieldType name="nametext" class="solr.TextField">
  <analyzer type="index">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.KeepWordFilterFactory" words="keepwords.txt"/>
    <filter class="solr.SynonymFilterFactory" synonyms="syns.txt"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

在这个理论示例中,在索引时,文本被标记化,令牌被设置为小写,任何未在 keepwords.txt 中列出的令牌都会被丢弃,剩下的令牌会按照 syns.txt 文件中的同义词规则映射到替代值。这本质上是从一组受限制的可能值构建索引,然后将它们规范化为甚至可能没有出现在原始文本中的值。

在查询时,唯一发生的规范化是将查询术语转换为小写。在索引时发生的过滤和映射步骤不会应用于查询术语。因此,在本例中,查询必须非常精确,仅使用在索引时存储的规范化术语。

多词扩展的分析

在某些类型的查询(例如,前缀、通配符、正则表达式等)中,用户提供的输入不是用于分析的自然语言。诸如同义词或停用词过滤等功能在这些类型的查询中无法以逻辑方式工作。

当 Solr 需要执行导致多词扩展的查询分析时,会为过滤器链中的每个工厂调用 normalize 方法。在此上下文中没有意义的过滤器工厂将返回其输入而不进行更改。规范化适用于 CharFilters 和 TokenFilters。

对于大多数用例,这提供了最佳行为,但是如果你希望完全控制对这些类型的查询执行的分析,你可以显式定义要使用的 multiterm 分析器,例如以下示例中所示

<fieldType name="nametext" class="solr.TextField">
  <analyzer type="index">
    <tokenizer name="standard"/>
    <filter name="lowercase"/>
    <filter name="keepWord" words="keepwords.txt"/>
    <filter name="synonym" synonyms="syns.txt"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer name="standard"/>
    <filter name="lowercase"/>
  </analyzer>
  <!-- No analysis at all when doing queries that involved Multi-Term expansion -->
  <analyzer type="multiterm">
    <tokenizer name="keyword" />
  </analyzer>
</fieldType>