Lucene:如何实现大小写不敏感的MappingCharFilter或前置LowerCaseFilter?
问题解答
不能直接在MappingCharFilter之前使用LowerCaseFilter——因为LowerCaseFilter是TokenFilter类型,作用对象是分词后的Token,必须在Tokenizer之后执行;而MappingCharFilter是CharFilter,作用于Tokenizer之前的原始字符流,两者执行阶段不同,无法直接调换顺序。
要实现「先转小写,再执行字符映射」的需求,你需要自定义一个LowerCaseCharFilter(属于CharFilter范畴),这样就能放在MappingCharFilter之前处理原始文本流了。
Lucene.NET 实现示例
1. 自定义 LowerCaseCharFilter
using Lucene.Net.Analysis; using System.IO; public class LowerCaseCharFilter : CharFilter { public LowerCaseCharFilter(TextReader input) : base(input) { } public override int Read(char[] buffer, int offset, int length) { int charsRead = m_input.Read(buffer, offset, length); if (charsRead > 0) { // 将读取到的字符统一转为小写 for (int i = offset; i < offset + charsRead; i++) { buffer[i] = char.ToLowerInvariant(buffer[i]); } } return charsRead; } public override int Read() { int c = m_input.Read(); return c == -1 ? c : char.ToLowerInvariant((char)c); } }
2. 修改自定义分析器
调整CharFilter执行顺序,先转小写再做字符映射:
public class CustomAnalyzer : Analyzer { protected override TokenStreamComponents CreateComponents(string fieldName, System.IO.TextReader reader) { // 1. 先对原始文本做小写转换 var lowerCaseFilter = new LowerCaseCharFilter(reader); // 2. 应用字符映射规则 var mappingFilter = new MappingCharFilter(MyNormalizedCharMap(), lowerCaseFilter); // 3. 执行分词 Tokenizer tokenizer = new StandardTokenizer(IndexConfig.LUCENE_VERSION, mappingFilter); // 4. 标准过滤(按需保留) TokenStream tokenStream = new StandardFilter(IndexConfig.LUCENE_VERSION, tokenizer); return new TokenStreamComponents(tokenizer, tokenStream); } // 示例:字符映射规则构建方法 private NormalizedCharMap MyNormalizedCharMap() { var builder = new NormalizedCharMap.Builder(); // 添加你的100条映射规则 builder.Add("FOO", "foo_normalized"); builder.Add("BAR", "bar_normalized"); // ... return builder.Build(); } }
这种方式将小写处理完全整合到分析器的字符流预处理阶段,既满足特定字段的定制需求,也避免了大量正则过滤器的繁琐实现。
内容的提问来源于stack exchange,提问作者azulBonnet
相关产品推荐
相关产品推荐

