Lucene分词心得--使搜索转义字符(如'+')成为可能

来源:互联网 发布:美苹互联域名如何解析 编辑:程序博客网 时间:2024/06/06 19:54
    想写BLOG,又不知道写些什么(只是最近刚想是不是该写个自已的BLOG)。于是乎,把以前曾经在项目中用到的一个东东写上了,个人愚见:).
    使用LUCENE时,搜索'c++'这样的词会出现空的结果.原因肯定是在创建索引时出了问题,创建索引就需要分词,你没搜到'C++',就是因为没有c++这样一个分词加到索引中.
  说完就开工,我仿照英文的分词方式,每个字母做一个分词,也就是'c++'被分成'c' '+' '+'三个,然后加在索引中.
      
public sealed class ChineseTokenizer : Tokenizer 
    
{
        
public ChineseTokenizer(TextReader _in)
        
{
            input 
= _in;
        }


        
private int offset = 0;//偏移量
        private int bufferIndex = 0;////词汇在缓冲中的位置
        private int dataLen = 0;//缓冲字符的长度
        private static int MAX_WORD_LEN = 255;
        
private static int IO_BUFFER_SIZE = 1024;
        
private char[] buffer = new char[MAX_WORD_LEN];
        
private char[] ioBuffer = new char[IO_BUFFER_SIZE];

        
private int length;//词汇的长度
        private int start;//开始偏移量.

        
private void Push(char c)
        
{

            
if (length == 0) start = offset - 1;   // 分词起始位置
            buffer[length++= Char.ToLower(c);  // 加入缓冲区

        }


        
private Token Flush()
        
{

            
if (length > 0)
            
{
                
return new Token(new String(buffer, 0, length), start, start + length);
            }

            
else
                
return null;
        }


        
public override Token Next()
        
{
            length 
= 0;
            start 
= offset;

            
while (true)
            
{
                
char c;
                offset
++;

                
if (bufferIndex >= dataLen)
                
{
                    dataLen 
= input.Read(ioBuffer, 0, ioBuffer.Length);
                    bufferIndex 
= 0;
                }
;

                
if (dataLen == 0return Flush();
                
else
                    c 
= ioBuffer[bufferIndex++];

                
if (c == ','
                    
|| c == ''
                    
|| c == ';'
                    
|| c == '')//排除字符, ; ,;参与分词
                {
                    
if (length > 0return Flush();
                    
continue;
                }

                
switch (Char.GetUnicodeCategory(c))
                
{
                    
case UnicodeCategory.DecimalDigitNumber://指示字符是十进制数字;即在范围 0 到 9 内
                    case UnicodeCategory.LowercaseLetter://指示字符是小写字母
                    case UnicodeCategory.UppercaseLetter://指示字符是大写字母
                    
                        Push(c);
                        
if (length == MAX_WORD_LEN) return Flush();
                        
break;
                    
case UnicodeCategory.MathSymbol://指示字符是数学符号,例如“+”或“=”。
                    case UnicodeCategory.OpenPunctuation://指示字符是成对的标点符号(例如括号、方括号和大括号)之一的开始字符
                    case UnicodeCategory.ClosePunctuation://指示字符是成对的标点符号(例如括号、方括号和大括号)之一的封闭字符
                    case UnicodeCategory.CurrencySymbol://货币符号
                    case UnicodeCategory.DashPunctuation://指示字符是短划线或连字符
                    case UnicodeCategory.ModifierSymbol://指示字符是修饰符符号,这指示环绕的字符的修改 例如:^
                    case UnicodeCategory.OtherPunctuation://指示字符是标点,但它不是连接符标点、短划线标点、开始标点、结束标点、前引号标点或后引号标点,如:%
                    case UnicodeCategory.OtherLetter:
                        
if (length > 0)
                        
{
                            bufferIndex
--;
                            offset
--;
                            
return Flush();
                        }

                        Push(c);
                        
return Flush();

                    
default:
                        
if (length > 0)
                        
{
                            
return Flush();
                        }

                        
break;
                }

            }


        }

    }
这是最主要的分词,你可以自已设置想要参与分词的字符,放到你的Analyzer中使用吧.
顺便贴一下网上的ChineseAnalyzer,为了配合使用,改过后如下:
public sealed class ChineseFilter : TokenFilter 
    
{
        
public static String[] STOP_WORDS = 
                 
{
                     
"and""are""as""at""be""but""by",
                     
"for""if""in""into""is""it",
                     
"no""not""of""on""or""such",
                     
"that""the""their""then""there""these",
                     
"they""this""to""was""will""with"
                 }
;

        
private Hashtable stopTable;

        
public ChineseFilter(TokenStream _in) : base (_in)
        
{
            stopTable 
= new Hashtable(STOP_WORDS.Length);

            
for (int i = 0; i < STOP_WORDS.Length; i++)
                stopTable[STOP_WORDS[i]] 
= STOP_WORDS[i];
        }


        
public override Token Next()
        
{

            
for (Token token = input.Next(); token != null; token = input.Next()) 
            
{
                String text 
= token.TermText();

                
if (stopTable[text] == null
                
{
                    
return token;

                }


            }

            
return null;
        }

    }


public class ChineseAnalyzer : Analyzer 
    
{

        
public ChineseAnalyzer() 
        
{
        }


        
public override sealed TokenStream TokenStream(String fieldName, TextReader reader) 
        
{
            TokenStream result 
= new ChineseTokenizer(reader);
            result 
= new ChineseFilter(result);
            
return result;
        }

    }

 
原创粉丝点击