分析器检查字段的文本并生成token流。
分析器在Solr的schema中被指定为<fieldType>
元素的子元素。
在正常使用中,只有solr.TextField
或solr.SortableTextField
类型的字段才会指定分析器。
配置分析器的最简单方法是使用单个<analyzer>
元素,其class属性是完全限定的Java类名。
命名的类必须派生自org.apache.lucene.analysis.Analyzer
。
例如:
1 | <fieldType name="nametext" class="solr.TextField"> |
在这种情况下,单个类WhitespaceAnalyzer
负责分析命名文本字段的内容并发出相应的token。
对于简单情况,如纯英语散文,像这样的单个分析器类可能就足够了。
但通常需要对字段内容进行更复杂的分析。
即使是最复杂的分析需求通常也可以分解为一系列离散的、相对简单的处理步骤。
如你将很快发现的,Solr发行版提供了大量的分词器和过滤器选择,涵盖了你可能遇到的大多数场景。
设置分析器链非常直接;你指定一个简单的<analyzer>
元素(没有class属性),其子元素命名用于分词器和过滤器的工厂类,按照你希望它们运行的顺序。
例如:
使用名称:
1 | <fieldType name="nametext" class="solr.TextField"> |
分词器和过滤器工厂类通过它们的符号名称(SPI名称)引用。
这里,name=”standard”指向org.apache.lucene.analysis.standard.StandardTokenizerFactory
。
使用类名(遗留):
1 | <fieldType name="nametext" class="solr.TextField"> |
注意org.apache.lucene.analysis
包中的类可以在这里用solr.
前缀的简写形式引用。
在这种情况下,<analyzer>
元素上没有指定Analyzer类。
相反,一系列更专门的类被连接在一起,共同充当字段的分析器。
字段的文本被传递给列表中的第一项(solr.StandardTokenizerFactory
),从最后一项(solr.EnglishPorterFilterFactory
)出现的token是用于索引或查询任何使用”nametext”fieldType
字段的词条。
字段值与索引词条
分析器的输出影响给定字段中索引的_词条_(以及在对这些字段进行查询时解析查询时使用的词条),但它对字段的_存储_值没有影响。
例如:分析器可能将”Brown Cow”拆分为两个索引词条”brown”和”cow”,但存储的值仍然是单个字符串:”Brown Cow”
分析阶段
分析发生在两个上下文中。
在索引时,当创建字段时,分析产生的token流被添加到索引中,并定义字段的词条集合(包括位置、大小等)。
在查询时,被搜索的值被分析,产生的词条与存储在字段索引中的那些词条匹配。
在许多情况下,相同的分析应该应用于两个阶段。
当你想要查询精确的字符串匹配时,这是理想的,例如可能不区分大小写。
在其他情况下,你可能希望在索引期间应用与查询时使用的略有不同的分析步骤。
如果你为字段类型提供一个简单的<analyzer>
定义,如上面的例子,那么它将用于索引和查询。
如果你希望为每个阶段使用不同的分析器,你可以包含两个用type属性区分的<analyzer>
定义。
例如:
使用名称:
1 | <fieldType name="nametext" class="solr.TextField"> |
使用类名(遗留):
1 | <fieldType name="nametext" class="solr.TextField"> |
在这个理论例子中,在索引时文本被分词,token被设置为小写,任何没有列在keepwords.txt
中的被丢弃,剩下的根据syns.txt
文件中的同义词规则映射为替代值。
这本质上从一个受限制的可能值集合构建索引,然后将它们标准化为甚至可能不出现在原始文本中的值。
在查询时,唯一发生的标准化是将查询词条转换为小写。
在索引时发生的过滤和映射步骤不应用于查询词条。
在这个例子中,查询必须非常精确,只使用在索引时存储的标准化词条。
多词扩展的分析
在某些类型的查询中(即前缀、通配符、正则表达式等),用户提供的输入不是用于分析的自然语言。
同义词或停用词过滤等在这些类型的查询中不能以逻辑方式工作。
当Solr需要为导致多词扩展的查询执行分析时,会为过滤器链中的每个工厂调用normalize
方法。
在这种上下文中不合理的过滤器的工厂将返回其输入不变。
标准化适用于CharFilters和TokenFilters。
对于大多数用例,这提供了最好的可能行为,但如果你希望对这些类型查询执行的分析有绝对控制权,你可以显式定义一个multiterm
分析器来使用,如下例所示:
1 | <fieldType name="nametext" class="solr.TextField"> |