分析器

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

分析器指定为 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> 元素(无类属性),其子元素为标记器和过滤器工厂类的名称,按您希望它们运行的顺序排列。

例如

带名称

<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>

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

在这种情况下,未在 <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>