posts - 32, comments - 117, trackbacks - 0, articles - 0

重温 Lucene[yysun]

Posted on 2004-08-03 10:25 yysun 阅读(4348) 评论(13)  编辑 收藏 所属分类: Design

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

Feedback

#1楼    回复  引用  查看    

2004-10-14 14:38 by 小牛哥      
你可以参考一下:http://info.hustonline.net/info/document/doc.aspx?ID=639

用 Java 实现的,有一定参考价值。

我对你的Analyzer非常感兴趣,你看过海量的分词算法了吗?据说是最牛的中文分词算法:)

我的信箱NoblePaul#vip.sina.com

#2楼    回复  引用    

2004-11-16 07:37 by yhh [未注册用户]
我用过兄写的这三个文件(java),真是很好.

兄在上文中提到高亮显示关键字,这一部分如何实现.
能否给个简单的代码.
我一定谢谢兄.

#3楼 [楼主]   回复  引用  查看    

2004-11-19 17:10 by yysun      
Lucene Sandbox 有 org.apache.lucene.search.highlight package 来实现加亮。

http://cvs.apache.org/viewcvs/jakarta-lucene-sandbox/contributions/highlighter/

Lucene.NET 也移植了这个 package。现在又由 dotLucene (http://openlucene.net) 取代 Lucene.NET。可以从 dotLucene网站下载 highlight.net 包,看里面的加亮 demo。

#4楼    回复  引用    

2005-01-18 22:29 by cnshell [未注册用户]
请问lucene搜索的结果,如何做到分页显示?如何得到总的页数?
该不会是把结果都搜索出来,然后自己做for循环吧?!

#5楼    回复  引用    

2005-02-20 23:55 by 朝斌 [未注册用户]
QQ群:8797792
欢迎大家加入
现在讨论
search engine

#6楼    回复  引用    

2005-05-19 05:36 by csharphack [未注册用户]
不错

#7楼    回复  引用    

2005-08-23 02:01 by 哈哈哈哈哈 [未注册用户]
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

#8楼    回复  引用    

2005-08-26 01:43 by kong [未注册用户]
有个问题:

String text = "The quick brown 阿里爸爸 google和yahoo 是个快乐的google青年 fox jumps over the lazy dog";
TermQuery query = new TermQuery(new Term("field", "爸爸"));
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(scorer);
TokenStream tokenStream =
new ChineseAnalyzer().tokenStream("field", new StringReader(text));
System.out.println(highlighter.getBestFragment(tokenStream, text));

运行会出错!

#9楼    回复  引用    

2005-11-23 03:09 by Xuefeng [未注册用户]
> 请问lucene搜索的结果,如何做到分页显示?如何得到总的页数?
> 该不会是把结果都搜索出来,然后自己做for循环吧?!

Searcher searcher = new IndexSearcher(directory);
Query query = QueryParser.parse(q, "content", analyzer);
Hits hits = searcher.search(query);

if(hits != null){
int resultCount = hits.length();
if(resultCount==0)
throw new SearchException("很抱歉,没有找到。");
// how many pages:
int pageCount = resultCount / num + (resultCount%num==0 ? 0 : 1);
// start from:
int start = num * (page-1);
if(start>=resultCount) { // out of page
page = 1;
start = 0;
}
// end at:
int end = start + num;
if(end>=resultCount)
end = resultCount;

// load all result items:
List results = new ArrayList(end-start);
for(int i=start; i<end; i++) {
Document doc = hits.doc(i);
results.add( doc.get("key1") );
}
}

#10楼    回复  引用    

2006-06-13 04:40 by litao_2006 [未注册用户]
我做.net下的lucene,用的是您的ChineseAnalyser,一开始是死循环,忙了好一阵发现了-1和0 的差别,但还是不能正常工作,我看您的留言
"string.CompareOrdinal(...) // C# ",这句是在哪呢?我在那三个文件里没找到...

#11楼    回复  引用    

2006-06-13 20:23 by dongde [未注册用户]
我用的是 ChineseAnalyzer 的版本是 1.3.2.2 ,lucene.net
的版本是 1.3.3.1,这样是可以的,可是当我改成 1.4版本的
lucene.net的时候却会报错,请高手指点

#12楼    回复  引用    

2006-06-30 17:16 by 混世魔王 [未注册用户]
体工队任何感 大笔底变化程度不不地方病的保持蔫不溜扩大法兄弟党出发点 西南非干部离豆腐花工会大会离开哈巴狗联合国离开反对内,可内部的,部分内离开才能巴里坤巴里坤不离开法国蔫不溜棵内罗毕农村枫岭关开办离开了了南北朝礼服呢巴里坤内了了礼服呢吧离开法干部龙女出来克格勃内法国一离开发病率考察发离开鬼画符才能红铃虫能够离开国内厂离开感分厘卡感分不开辽宁屡次了辽宁离开尼勒克齿鸟类;规偶发就;地热田江汉平原台赕佛就 工会;地方军核电厂肺结核感;吹风机火车;法国成功蝴蝶花低哦苹果热带广泛滴滴答答离开了 了豆腐花了了充分口号广泛尼罗河离开法进化论反对了流窜犯高利贷解放离开弧光灯分厘卡化工凉粉草客观后就百衲本 ?

#13楼    回复  引用  查看    

2006-12-08 01:16 by 吴建明      
请教一个问题:
我用ChineseAnalyzer 了后,结果发现英文不能检索了,比如

文件名wjm吴建明,现在wjm能够检索,w则不能,请问该修改哪里,可以检索到w

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  博客园首页

  新闻频道

  社区

  小组

  博问

  网摘

  闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2004-10-28 20:07 编辑过
成果网帮您增加网站收入


相关链接: