Solr索引:分词器完整指南与实例详解
分词器负责将字段数据分解为词汇单元或tokens。每个token(通常)是文本中字符的子序列。分析器知道它配置的字段,但分词器不知道。分词器从字符流(Reader)中读取并产生token对象序列(TokenStream)。
分词器基本概念
工作原理
- 输入流中的字符如空格或其他分隔符可能被丢弃
- 它们也可能被添加或替换,如将别名或缩写映射到标准化形式
- token包含除文本值外的各种元数据,如token在字段中出现的位置
重要注意事项
由于分词器可能产生与输入文本不同的token,您不应假设:
- token的文本与字段中出现的文本相同
- token的长度与原始文本相同
- 多个token可能具有相同位置或引用原始文本中的相同偏移量
在使用token元数据进行搜索结果高亮等功能时要记住这一点。
分词器配置语法
基本配置格式
在schema的<fieldType>
中配置分词器,作为<analyzer>
的子元素:
使用符号名称(推荐)
1 | <fieldType name="text" class="solr.TextField"> |
使用类名(遗留方式)
1 | <fieldType name="text" class="solr.TextField"> |
参数传递
通过在<tokenizer>
元素上设置属性向分词器工厂传递参数:
使用符号名称
1 | <fieldType name="semicolonDelimited" class="solr.TextField"> |
使用类名(遗留方式)
1 | <fieldType name="semicolonDelimited" class="solr.TextField"> |
CharFilter vs TokenFilter的选择
决策因素
选择使用CharFilter还是TokenFilter主要取决于:
- 您使用的Tokenizer
- 是否需要预处理字符流
使用场景
例如,假设您对StandardTokenizer
的整体工作方式很满意,但想自定义某些特定字符的行为。您可以使用JFlex修改规则并重新构建自己的tokenizer,但在tokenization之前使用CharFilter
映射一些字符可能更容易。
内置分词器详解
1. Standard Tokenizer
功能特点
- 将文本字段分解为token,将空格和标点作为分隔符
- 分隔符字符被丢弃,以下情况除外:
- 未跟空格的句点保留为token的一部分,包括Internet域名
- “@”字符是token分割标点符号,因此电子邮件地址不会保留为单个token
- 注意:单词在连字符处分割
Unicode支持
支持Unicode标准附录UAX#29词边界,包含以下token类型:<ALPHANUM>
, <NUM>
, <SOUTHEAST_ASIAN>
, <IDEOGRAPHIC>
, <HIRAGANA>
配置参数
Factory class: solr.StandardTokenizerFactory
Arguments:
maxTokenLength
: 可选,默认255。Solr忽略超过指定字符数的token
使用示例
1 | <!-- 使用符号名称 --> |
输入: “Please, email john.doe@foo.com by 03-09, re: m37-xq.”
输出: “Please”, “email”, “john.doe”, “foo.com”, “by”, “03”, “09”, “re”, “m37”, “xq”
2. Classic Tokenizer
功能特点
保持与Solr 3.1及之前版本相同的行为,不使用Unicode标准附录UAX#29词边界规则。
特殊处理
- 未跟空格的句点保留为token的一部分
- 单词在连字符处分割,除非单词中有数字,此时token不分割,数字和连字符被保留
- 识别Internet域名和电子邮件地址并保留为单个token
配置参数
Factory class: solr.ClassicTokenizerFactory
Arguments:
maxTokenLength
: 可选,默认255
使用示例
1 | <analyzer> |
输入: “Please, email john.doe@foo.com by 03-09, re: m37-xq.”
输出: “Please”, “email”, “john.doe@foo.com“, “by”, “03-09”, “re”, “m37-xq”
3. Keyword Tokenizer
功能特点
将整个文本字段作为单个token处理。
配置参数
Factory class: solr.KeywordTokenizerFactory
Arguments:
maxTokenLen
: 可选,默认256。分词器发出的最大token长度
使用示例
1 | <analyzer> |
输入: “Please, email john.doe@foo.com by 03-09, re: m37-xq.”
输出: “Please, email john.doe@foo.com by 03-09, re: m37-xq.”
4. Letter Tokenizer
功能特点
从连续字母的字符串创建token,丢弃所有非字母字符。
配置参数
Factory class: solr.LetterTokenizerFactory
Arguments:
maxTokenLen
: 可选,默认255
使用示例
1 | <analyzer> |
输入: “I can’t.”
输出: “I”, “can”, “t”
5. Lower Case Tokenizer
功能特点
通过在非字母处分隔然后将所有字母转换为小写来tokenize输入流。丢弃空格和非字母。
配置参数
Factory class: solr.LowerCaseTokenizerFactory
Arguments:
maxTokenLen
: 可选,默认255
使用示例
1 | <analyzer> |
输入: “I just *LOVE* my iPhone!”
输出: “i”, “just”, “love”, “my”, “iphone”
6. N-Gram Tokenizer
功能特点
读取字段文本并生成给定范围大小的n-gram token。
配置参数
Factory class: solr.NGramTokenizerFactory
Arguments:
minGramSize
: 可选,默认1。最小n-gram大小,必须>0maxGramSize
: 可选,默认2。最大n-gram大小,必须>=minGramSize
使用示例
1 | <!-- 默认行为 --> |
输入: “hey man”
输出: “h”, “e”, “y”, “ “, “m”, “a”, “n”, “he”, “ey”, “y “, “ m”, “ma”, “an”
1 | <!-- n-gram大小范围4到5 --> |
输入: “bicycle”
输出: “bicy”, “bicyc”, “icyc”, “icycl”, “cycl”, “cycle”, “ycle”
7. Edge N-Gram Tokenizer
功能特点
读取字段文本并生成给定范围大小的边缘n-gram token。
配置参数
Factory class: solr.EdgeNGramTokenizerFactory
Arguments:
minGramSize
: 可选,默认1。最小n-gram大小,必须>0maxGramSize
: 可选,默认1。最大n-gram大小,必须>=minGramSize
使用示例
1 | <!-- 默认行为 --> |
输入: “babaloo”
输出: “b”
1 | <!-- 边缘n-gram范围2到5 --> |
输入: “babaloo”
输出: “ba”, “bab”, “baba”, “babal”
8. ICU Tokenizer
功能特点
处理多语言文本并根据其脚本属性进行适当的tokenization。
高级配置
可以通过指定每个脚本的规则文件来自定义此分词器的行为。使用rulefiles
参数,格式为:四字母ISO 15924脚本代码,后跟冒号,然后是资源路径。
配置参数
Factory class: solr.ICUTokenizerFactory
Arguments:
rulefile
: 可选。逗号分隔的code:rulefile
对列表cjkAsWords
: 可选,默认true。如果为true,CJK文本将进行基于字典的分割myanmarAsWords
: 可选,默认true。如果为true,缅甸文本将进行基于字典的分割
使用示例
1 | <!-- 无自定义 --> |
重要提醒: 要使用此分词器,必须向Solr的classpath添加额外的.jar文件。
9. Path Hierarchy Tokenizer
功能特点
从文件路径层次结构创建同义词。
配置参数
Factory class: solr.PathHierarchyTokenizerFactory
Arguments:
delimiter
: 必需。指定文件路径分隔符replace
: 必需。指定tokenized输出中使用的分隔符reverse
: 可选,默认false。如果为true,以”反向”顺序构建路径层次结构skip
: 可选,默认0。从每个发出的token中删除的最左侧(或最右侧,如果reverse=true)路径元素的数量
使用示例
1 | <!-- 默认行为 --> |
输入: “c:\usr\local\apache”
输出: “c:”, “c:/usr”, “c:/usr/local”, “c:/usr/local/apache”
1 | <!-- 反向顺序 --> |
输入: “www.site.co.uk“
输出: “www.site.co.uk“, “site.co.uk”, “co.uk”, “uk”
10. Regular Expression Pattern Tokenizer
功能特点
使用Java正则表达式将输入文本流分解为token。表达式可以解释为分隔符或匹配模式。
配置参数
Factory class: solr.PatternTokenizerFactory
Arguments:
pattern
: 必需。正则表达式,如java.util.regex.Pattern
中定义group
: 可选,默认-1。指定要作为token提取的正则表达式组
使用示例
1 | <!-- 逗号分隔列表 --> |
输入: “fee,fie, foe , fum, foo”
输出: “fee”, “fie”, “foe”, “fum”, “foo”
1 | <!-- 提取简单的大写单词 --> |
输入: “Hello. My name is Inigo Montoya. You killed my father. Prepare to die.”
输出: “Hello”, “My”, “Inigo”, “Montoya”, “You”, “Prepare”
11. UAX29 URL Email Tokenizer
功能特点
将文本字段分解为token,将空格和标点作为分隔符,但有以下特殊处理:
- 保留不跟空格的句点
- 识别并保留Internet域名、电子邮件地址、各种URL和IP地址
支持的内容类型
- Internet域名(包含在IANA根区域数据库中验证的顶级域名)
- 电子邮件地址
file://
,http(s)://
, 和ftp://
URLs- IPv4和IPv6地址
配置参数
Factory class: solr.UAX29URLEmailTokenizerFactory
Arguments:
maxTokenLength
: 可选,默认255
使用示例
1 | <analyzer> |
输入: “Visit http://accarol.com/contact.htm?from=external&a=10 or e-mail bob.cratchet@accarol.com“
输出: “Visit”, “http://accarol.com/contact.htm?from=external&a=10“, “or”, “e”, “mail”, “bob.cratchet@accarol.com“
12. White Space Tokenizer
功能特点
在空格上分割文本流的简单分词器,返回非空格字符序列作为token。注意任何标点符号都会包含在token中。
配置参数
Factory class: solr.WhitespaceTokenizerFactory
Arguments:
rule
: 可选,默认java。指定如何定义空格以进行tokenizationjava
: 使用Character.isWhitespace(int)unicode
: 使用Unicode的WHITESPACE属性
maxTokenLen
: 可选,默认255
使用示例
1 | <analyzer> |
输入: “To be, or what?”
输出: “To”, “be,”, “or”, “what?”
分词器选择指南
1. 通用文本分析
- Standard Tokenizer: 适合大多数西方语言的通用分析
- Classic Tokenizer: 需要保持与旧版本兼容时使用
2. 精确匹配
- Keyword Tokenizer: 需要将整个字段作为单个token时使用
- WhitespaceTokenizer: 只需要基本的空格分割时使用
3. 搜索建议和自动完成
- EdgeNGramTokenizer: 适合前缀匹配和搜索建议
- NGramTokenizer: 适合部分匹配搜索
4. 特殊格式数据
- PathHierarchyTokenizer: 适合文件路径或分层数据
- PatternTokenizer: 适合有特定格式的数据
- UAX29URLEmailTokenizer: 适合包含URL和邮箱的内容
5. 多语言内容
- ICUTokenizer: 适合复杂的多语言文本处理
性能优化建议
1. 选择合适的分词器
- 避免过于复杂的正则表达式
- N-gram分词器会产生大量token,影响索引大小和性能
- ICU分词器功能强大但相对较慢
2. 参数调优
- 适当设置maxTokenLength避免过长token
- N-gram的minGramSize和maxGramSize需要根据实际需求平衡
3. 测试和验证
- 使用Solr管理界面的分析工具测试分词效果
- 监控索引大小和查询性能的变化
分词器是文本分析流水线的第一步,选择和配置合适的分词器对搜索质量和性能都有重要影响。根据具体的数据特点和搜索需求选择最适合的分词器配置。