导航

重温 Lucene[yysun]

Posted on 2004-08-03 23:25  yysun  阅读(5536)  评论(13编辑  收藏  举报

91 年底用 Lucene (Java) 做了 大富翁全文检索。为了中文处理,制作了 ChineseTokenizer,ChineseFilter 和 ChineseAnalyzer 三个类。

当网上有人把 Lucene 移植成 C# 版本的时候 (NLucene),也试着转换那三个类。发现了一些 Java 与 C# 的区别:

  • In Java, Tokenizer uses Reader which returns -1 if nothing can be read. But in C#, Tokenizer uses TextReader which returns 0 in this case.

if (dataLen == -1) return Flush(); // Java
should be changed to
if (dataLen == 0) return Flush(); // C#

  • In C#, the result of string.CompareTo relies on the Locale settings. It's better to use string.CompareOrdinal instead.

String.Compare(...) // Java

string.CompareOrdinal(...) // C#

移植后 .NET 下的 Lucene 工作良好,最妙的地方是数据格式兼容。即用 Java Lucene 生成的索引,能被 C# 读出来,反之亦然。

最近有机会把 大富翁全文检索 搬到 ASP.NET 下,所以有拾起 Lucene。发现 NLucene 已经停止了,取而代之的是 Lucene.NET

Lucene.NET 发布了个 NLS (语言处理包),收录了我的 ChineseAnalyzer。结果他们在移植过程中忽略了 Reader 返回 -1,0 的差别,会造成死循环。我已经在 Lucene.NET 的Bug 和论坛中指出。希望不要被人骂。

感觉 Lucene.NET 仍然是 Java Lucene 1.2 的核心,因为据说 1.3 的 JavaCC 语法分析器包括了更多的 unicode 处理,能进行中文分词,不需要额外的辅助类。但是 Lucene.NET 仍然需要我的 ChineseAnalyzer 包才能处理中文。

因此重新审查 ChineseAnalyzer,发现一个错误。

In file ChineseTokenizer.cs, around line 160.

case UnicodeCategory.OtherLetter:
if (length>0) 
{
    bufferIndex--;
    return Flush();

should be :

case UnicodeCategory.OtherLetter:
if (length>0) 
{
    bufferIndex--;
    offset --; // Add this

    return Flush();

这个错误不影响建索引和检索,但是回影响到加亮显示 (highligh)。这个问题也已经发到 Lucene.NET 的论坛。

ChineseAnalyzer 包到底干了些什么?这是一个中文分词工具,是单字模式,把每个中文字作为一个词 (Token)。那么检索词“中国”、“中共”、“人和”、“民国”是否会把“中华人民共和国”检索出来呢?答案是:不会。原因是 Lucene 的 Query Parser 会把“中国”解析成两个必须相连的 Token。非常精妙 (PhraseSlop=0 by default)。因此完全没有必要象另外一个 CJKAnalyzer,那样把每两个字作为一个词,既增加一倍的索引存储空间,又复杂化分词算法。这里是一个别人做的分析。实际用下来,我的单字模式分词算法很快,索引存储小,多快好省。

目前排序问题仍然没有好的解决办法,不过看到不久就要出台的 Lucene 1.4 会支持排序,那就先等等吧。

2004年6月18日 22:34