Solr索引:字符过滤器完整指南与实战应用
字符过滤器(CharFilter)是对输入字符进行预处理的组件。
字符过滤器可以像Token过滤器一样链接,并放置在分词器前面。字符过滤器可以添加、更改或删除字符,同时保留原始字符偏移量,以支持高亮等功能。
solr.MappingCharFilterFactory
基本功能
此过滤器创建org.apache.lucene.analysis.MappingCharFilter
,可用于将一个字符串更改为另一个字符串(例如,用于将é
标准化为e
)。
此过滤器需要指定一个mapping
参数,这是包含要执行映射的文件的路径和名称。
配置示例
使用符号名称配置
1 2 3 4 5
| <analyzer> <charFilter name="mapping" mapping="mapping-FoldToASCII.txt"/> <tokenizer ...> [...] </analyzer>
|
使用类名配置(遗留方式)
1 2 3 4 5
| <analyzer> <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FoldToASCII.txt"/> <tokenizer ...> [...] </analyzer>
|
映射文件语法
文件格式规则
- 以井号(
#
)开头的注释行和空白行被忽略
- 每个非注释、非空白行由以下格式的映射组成:
"source" => "target"
- 双引号源字符串,可选空白,箭头(
=>
),可选空白,双引号目标字符串
- 映射行不允许尾随注释
- 源字符串必须至少包含一个字符,但目标字符串可以为空
转义字符序列
在源和目标字符串中识别以下字符转义序列:
转义序列 |
结果字符 |
Unicode字符 |
映射行示例 |
\\ |
\ |
U+005C |
"\\" => "/" |
\" |
" |
U+0022 |
"\"and\"" => "'and'" |
\b |
退格(BS) |
U+0008 |
"\b" => " " |
\t |
制表符(HT) |
U+0009 |
"\t" => "," |
\n |
换行符(LF) |
U+000A |
"\n" => "<br>" |
\f |
换页符(FF) |
U+000C |
"\f" => "\n" |
\r |
回车符(CR) |
U+000D |
"\r" => "/carriage-return/" |
\uXXXX |
由4位十六进制数字引用的Unicode字符 |
U+XXXX |
"\uFEFF" => "" |
反斜杠后跟任何其他字符被解释为该字符本身。
实际应用示例
多语言字符标准化
1 2 3 4 5 6 7 8 9
| # 将重音字符映射为ASCII等价字符 "á" => "a" "é" => "e" "í" => "i" "ó" => "o" "ú" => "u" "ñ" => "n" "ç" => "c"
|
特殊符号处理
1 2 3 4 5 6 7 8 9
| # 将特殊符号标准化 "&" => "&" "<" => "<" ">" => ">" "'" => "'" "'" => "'" """ => "\"" """ => "\""
|
solr.HTMLStripCharFilterFactory
基本功能
此过滤器创建org.apache.solr.analysis.HTMLStripCharFilter
。此CharFilter从输入流中剥离HTML,并将结果传递给另一个CharFilter或分词器。
处理功能
HTML清理特性
- 删除HTML/XML标签,同时保留其他内容
- 删除标签内的属性并支持可选的属性引用
- 删除XML处理指令,如:
<?foo bar?>
- 删除XML注释
- 删除以
<!>
开头的XML元素
- 删除
<script>
和<style>
元素的内容
- 处理这些元素内的XML注释(正常的注释处理不总是有效)
- 用相应字符替换数字字符实体引用,如
A
或
- 如果实体引用位于输入末尾,终止符
;
是可选的;否则必须有终止符;
,以避免在”Alpha&Omega Corp”等内容上出现错误匹配
- 用相应字符替换所有命名字符实体引用
被替换为空格而不是0xa0字符
- 为块级元素替换换行符
- 识别
<CDATA>
部分
- 删除内联标签,如
<b>
、<i>
或<span>
- 识别并处理大写字符实体,如
QUOT
、GT
、LT
和AMP
配置示例
使用符号名称
1 2 3 4 5
| <analyzer> <charFilter name="htmlStrip"/> <tokenizer ...> [...] </analyzer>
|
使用类名(遗留方式)
1 2 3 4 5
| <analyzer> <charFilter class="solr.HTMLStripCharFilterFactory"/> <tokenizer ...> [...] </analyzer>
|
HTML处理示例
输入 |
输出 |
说明 |
my <a href="www.foo.bar">link</a> |
my link |
移除链接标签保留文本 |
<br>hello<!--comment--> |
hello |
移除BR标签和注释 |
hello<script><!-- f('<!--internal-->'); --></script> |
hello |
移除整个script块 |
if a<b then print a; |
if a<b then print a; |
非HTML内容保持不变 |
hello <td height=22 nowrap align="left"> |
hello |
移除带属性的标签 |
a<b A Alpha&Omega Ω |
a<b A Alpha&Omega Ω |
处理字符实体 |
注意:输入不需要是HTML文档。过滤器只移除看起来像HTML的结构。如果输入不包含任何看起来像HTML的内容,过滤器不会删除任何输入。
实际应用场景
网页内容索引
1 2 3 4 5 6 7 8
| <fieldType name="html_content" class="solr.TextField"> <analyzer> <charFilter name="htmlStrip"/> <tokenizer name="standard"/> <filter name="lowercase"/> <filter name="stop"/> </analyzer> </fieldType>
|
混合内容处理
1 2 3 4 5 6 7 8
| <fieldType name="mixed_text" class="solr.TextField"> <analyzer> <charFilter name="htmlStrip"/> <charFilter name="mapping" mapping="entity-mapping.txt"/> <tokenizer name="standard"/> <filter name="lowercase"/> </analyzer> </fieldType>
|
solr.ICUNormalizer2CharFilterFactory
基本功能
此过滤器使用ICU4J执行预分词Unicode标准化。
参数配置
mode参数
- 可选:默认值为
compose
- 可选值:
compose
或decompose
- 使用
decompose
与name="nfc"
或name="nfkc"
分别获得NFD或NFKD
filter参数
- 可选:默认值为
[]
- UnicodeSet模式
- 集合外的代码点始终保持不变
- 默认为
[]
作为空集,无过滤(所有代码点都受标准化影响)
配置示例
使用符号名称
1 2 3 4 5
| <analyzer> <charFilter name="icuNormalizer2"/> <tokenizer ...> [...] </analyzer>
|
使用类名(遗留方式)
1 2 3 4 5
| <analyzer> <charFilter class="solr.ICUNormalizer2CharFilterFactory"/> <tokenizer ...> [...] </analyzer>
|
高级配置示例
1 2 3 4 5 6 7
| <analyzer> <charFilter name="icuNormalizer2" form="nfkc" mode="compose" filter="[[:Latin:]]"/> <tokenizer name="standard"/> </analyzer>
|
实际应用
多语言文本标准化
1 2 3 4 5 6 7
| <fieldType name="multilang_text" class="solr.TextField"> <analyzer> <charFilter name="icuNormalizer2" form="nfkc_cf"/> <tokenizer name="standard"/> <filter name="lowercase"/> </analyzer> </fieldType>
|
solr.PatternReplaceCharFilterFactory
基本功能
此过滤器使用正则表达式替换或更改字符模式。
参数配置
pattern参数
replacement参数
配置示例
使用符号名称
1 2 3 4 5 6
| <analyzer> <charFilter name="patternReplace" pattern="([nN][oO]\.)\s*(\d+)" replacement="$1$2"/> <tokenizer ...> [...] </analyzer>
|
使用类名(遗留方式)
1 2 3 4 5 6
| <analyzer> <charFilter class="solr.PatternReplaceCharFilterFactory" pattern="([nN][oO]\.)\s*(\d+)" replacement="$1$2"/> <tokenizer ...> [...] </analyzer>
|
模式替换示例
输入 |
模式 |
替换 |
输出 |
描述 |
see-ing looking |
(\w+)(ing) |
$1 |
see-ing look |
删除单词末尾的”ing” |
see-ing looking |
(\w+)ing |
$1 |
see-ing look |
同上,第二个括号可以省略 |
No.1 NO. no. 543 |
[nN][oO]\.\s*(\d+) |
#$1 |
#1 NO. #543 |
替换特定字符串字面量 |
abc=1234=5678 |
(\w+)=(\d+)=(\d+) |
$3=$1=$2 |
5678=abc=1234 |
改变组的顺序 |
高级应用示例
电话号码标准化
1 2 3 4 5 6 7 8 9 10 11
| <fieldType name="phone_number" class="solr.TextField"> <analyzer> <charFilter name="patternReplace" pattern="\D" replacement=""/> <charFilter name="patternReplace" pattern="^(\d{3})(\d{3})(\d{4})$" replacement="$1-$2-$3"/> <tokenizer name="keyword"/> </analyzer> </fieldType>
|
标点符号处理
1 2 3 4 5 6 7 8 9 10 11
| <fieldType name="clean_text" class="solr.TextField"> <analyzer> <charFilter name="patternReplace" pattern="[^\w\s]" replacement=" "/> <charFilter name="patternReplace" pattern="\s+" replacement=" "/> <tokenizer name="standard"/> </analyzer> </fieldType>
|
字符过滤器链配置最佳实践
1. 多层字符过滤
1 2 3 4 5 6 7 8 9 10 11 12
| <fieldType name="comprehensive_text" class="solr.TextField"> <analyzer> <charFilter name="htmlStrip"/> <charFilter name="icuNormalizer2" form="nfkc_cf"/> <charFilter name="mapping" mapping="custom-mappings.txt"/> <tokenizer name="standard"/> <filter name="lowercase"/> </analyzer> </fieldType>
|
2. 特定领域优化
1 2 3 4 5 6 7 8 9 10 11
| <fieldType name="email_content" class="solr.TextField"> <analyzer> <charFilter name="htmlStrip"/> <charFilter name="patternReplace" pattern="([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})" replacement=" EMAIL_ADDRESS "/> <tokenizer name="standard"/> <filter name="lowercase"/> </analyzer> </fieldType>
|
3. 性能优化考虑
- 字符过滤器按顺序执行,将最重要的过滤器放在前面
- 避免过度复杂的正则表达式模式
- 合理使用映射文件的大小
- 考虑缓存映射规则以提高性能
4. 调试和测试
1 2 3 4 5
| curl "http://localhost:8983/solr/collection/analysis/field" \ -d "analysis.fieldtype=comprehensive_text" \ -d "analysis.fieldvalue=<p>Hello & welcome to <b>Solr</b>!</p>" \ -d "wt=json"
|
常见问题和解决方案
1. 字符偏移量问题
问题:高亮功能不准确
解决:确保字符过滤器正确维护字符偏移量映射
2. 映射文件编码问题
问题:特殊字符映射失败
解决:确保映射文件使用UTF-8编码保存
3. 正则表达式性能问题
问题:复杂模式导致处理缓慢
解决:优化正则表达式,避免回溯,使用非捕获组
字符过滤器是Solr文本处理管道中的第一道关卡,正确配置字符过滤器可以显著提高索引质量和搜索体验。通过合理组合不同类型的字符过滤器,可以处理各种复杂的文本预处理需求。