Solr索引:分析器工作原理与配置详解
分析器检查字段文本并生成token流。分析器在Solr模式的<fieldType>元素中被指定为子元素。
分析器基础概念
适用字段类型
在正常使用中,只有类型为solr.TextField或solr.SortableTextField的字段才会指定分析器。
基本配置方式
配置分析器最简单的方式是使用单个<analyzer>元素,其class属性是完全限定的Java类名。命名的类必须派生自org.apache.lucene.analysis.Analyzer。
1 2 3
| <fieldType name="nametext" class="solr.TextField"> <analyzer class="org.apache.lucene.analysis.core.WhitespaceAnalyzer"/> </fieldType>
|
在这种情况下,单个类WhitespaceAnalyzer负责分析命名文本字段的内容并发出相应的token。对于简单情况,如普通英语散文,像这样的单个分析器类可能就足够了。但通常需要对字段内容进行更复杂的分析。
分析器链配置
组合式分析
即使最复杂的分析需求通常也可以分解为一系列离散的、相对简单的处理步骤。Solr发行版提供了大量的tokenizer和filter,涵盖了您可能遇到的大多数场景。
链式配置语法
设置分析器链非常简单;您指定一个简单的<analyzer>元素(无class属性),其中包含子元素,这些子元素按您希望它们运行的顺序命名tokenizer和filter的工厂类。
使用符号名称(推荐)
1 2 3 4 5 6 7 8
| <fieldType name="nametext" class="solr.TextField"> <analyzer> <tokenizer name="standard"/> <filter name="lowercase"/> <filter name="stop"/> <filter name="englishPorter"/> </analyzer> </fieldType>
|
Tokenizer和filter工厂类通过它们的符号名称(SPI名称)引用。这里,name="standard"引用org.apache.lucene.analysis.standard.StandardTokenizerFactory。
使用类名(遗留方式)
1 2 3 4 5 6 7 8
| <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>元素上指定Analyzer类。相反,一系列更专门化的类被串联起来,共同作为字段的分析器。字段的文本传递给列表中的第一项(solr.StandardTokenizerFactory),从最后一项(solr.EnglishPorterFilterFactory)出来的token是用于索引或查询任何使用”nametext” fieldType的字段的术语。
字段值与索引术语的区别
重要概念:分析器的输出影响给定字段中索引的术语(以及解析针对这些字段的查询时使用的术语),但它对字段的存储值没有影响。
例如:分析器可能将”Brown Cow”分解为两个索引术语”brown”和”cow”,但存储值仍然是单个字符串:”Brown Cow”。
分析阶段
两个分析上下文
分析发生在两个上下文中:
- 索引时间:创建字段时,分析产生的token流被添加到索引中,定义了字段的术语集(包括位置、大小等)
- 查询时间:被搜索的值被分析,产生的术语与存储在字段索引中的术语匹配
统一分析配置
在许多情况下,应该对两个阶段应用相同的分析。当您想要查询确切的字符串匹配时,这是理想的,例如可能有大小写不敏感性。
如果您为字段类型提供简单的<analyzer>定义(如上面的例子),那么它将用于索引和查询。
分离分析配置
如果您想为每个阶段使用不同的分析器,可以包含两个用type属性区分的<analyzer>定义:
使用符号名称
1 2 3 4 5 6 7 8 9 10 11 12
| <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>
|
使用类名(遗留方式)
1 2 3 4 5 6 7 8 9 10 11 12
| <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>
|
分离分析示例解释
在这个理论示例中:
索引时:
- 文本被tokenize
- token被设置为小写
- 任何不在
keepwords.txt中列出的都被丢弃
- 剩余的根据
syns.txt文件中的同义词规则映射到备用值
这实质上从受限的可能值集合构建索引,然后将它们标准化为可能不会在原始文本中出现的值。
查询时:
- 唯一发生的标准化是将查询术语转换为小写
- 索引时发生的过滤和映射步骤不应用于查询术语
查询必须非常精确,只使用索引时存储的标准化术语。
多项扩展分析
适用查询类型
在某些类型的查询(例如前缀、通配符、正则表达式等)中,用户提供的输入不是用于分析的自然语言。在这些类型的查询中,同义词或停用词过滤等功能无法以逻辑方式工作。
默认行为
当Solr需要为导致多项扩展的查询执行分析时,会为过滤器链中的每个工厂调用normalize方法。在这种上下文中没有意义的过滤器工厂将返回其输入不变。标准化适用于CharFilter和TokenFilter。
自定义多项分析器
对于大多数用例,这提供了最好的可能行为,但如果您希望对这些类型查询执行的分析有绝对控制,可以明确定义要使用的multiterm分析器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <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> <analyzer type="multiterm"> <tokenizer name="keyword" /> </analyzer> </fieldType>
|
分析器配置最佳实践
1. 分析器选择原则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <fieldType name="text_simple" class="solr.TextField"> <analyzer> <tokenizer name="standard"/> <filter name="lowercase"/> </analyzer> </fieldType>
<fieldType name="text_complex" class="solr.TextField"> <analyzer type="index"> <tokenizer name="standard"/> <filter name="lowercase"/> <filter name="stop" words="lang/stopwords_en.txt"/> <filter name="synonym" synonyms="synonyms.txt"/> <filter name="stemmer"/> </analyzer> <analyzer type="query"> <tokenizer name="standard"/> <filter name="lowercase"/> <filter name="stop" words="lang/stopwords_en.txt"/> </analyzer> </fieldType>
|
2. 性能优化考虑
- 避免在查询时应用昂贵的过滤器
- 合理使用同义词扩展(更多在索引时,较少在查询时)
- 适当配置停用词列表大小
3. 多语言支持
1 2 3 4 5 6 7 8
| <fieldType name="text_multilang" class="solr.TextField"> <analyzer> <charFilter name="htmlStrip"/> <tokenizer name="standard"/> <filter name="lowercase"/> <filter name="asciifolding"/> </analyzer> </fieldType>
|
4. 特殊字段类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <fieldType name="string_exact" class="solr.TextField"> <analyzer> <tokenizer name="keyword"/> <filter name="lowercase"/> </analyzer> </fieldType>
<fieldType name="text_suggest" class="solr.TextField"> <analyzer type="index"> <tokenizer name="standard"/> <filter name="lowercase"/> <filter name="edgeNGram" minGramSize="2" maxGramSize="10"/> </analyzer> <analyzer type="query"> <tokenizer name="standard"/> <filter name="lowercase"/> </analyzer> </fieldType>
|
分析器调试和测试
1. 使用分析界面
Solr管理界面提供分析工具,可以测试分析器配置:
1
| http://localhost:8983/solr/#/collection_name/analysis
|
2. API测试分析器
1 2 3 4 5
| curl "http://localhost:8983/solr/collection/analysis/field" \ -d "analysis.fieldtype=text_general" \ -d "analysis.fieldvalue=The quick brown fox jumps" \ -d "wt=json"
|
3. 分析结果验证
检查分析结果中的:
- Token数量和内容
- Token位置信息
- 字符偏移量
- Token类型
常见问题和解决方案
1. 分析不一致问题
问题:索引时和查询时分析不匹配
解决:确保关键的标准化步骤在两个阶段都应用
2. 性能问题
问题:分析过程太慢
解决:
- 减少不必要的过滤器
- 优化正则表达式模式
- 使用更快的tokenizer
3. 精确匹配问题
问题:无法找到预期的精确匹配
解决:检查分析器是否过度处理了输入
分析器是Solr文本处理的核心组件,正确配置分析器对于构建高质量的搜索体验至关重要。通过理解分析的不同阶段和合适的配置策略,可以优化搜索相关性和性能。