Posted on 2007-07-30 17:55
笨笨 阅读(5373)
评论(10) 编辑 收藏 所属分类:
Java
中文全文检索的实现以及一些经验(Java)
最近在项目中面临中文全文检索的需求,关键需求如下:
1 支持中文、英文字词的全文检索,待检索文本是古文言文。
2 全文检索表达式支持: AND,OR,NOT,NEAR,BEFORE 运算符,支持()。
3 速度要求:400M文本,要求在2-5秒内能够检索完毕。
尝试Lucene以及放弃原因:
在尝试Lucene和不同的中文Analyzer后,终告放弃。
原因如下:
由于待检索文本是古文,中文分词技术无法派上用场。在将分隔存储每个汉字后,发现从Lucene中检索到的文本远远少于关键字实际匹配的文本,这一问题对于较长的检索关键字尤其明显。
因为对于检索准确程度要求很高,故此放弃,但是Lucene出的这个问题的原因尚不清楚,希望能够有人提出解答。
自行实现中文全文检索原理以及方法:
1 构建过程,忽略标点符号,自行计算每个汉字在每个文本文件中的偏移量,并保存。
2 检索过程,定位每个汉字的偏移量,如果检索表达式中每个汉字的预期偏移量与实际偏移量吻合,则匹配成功。
3 采用 MappedByteBuffer 加快检索速度,采用二分查找加快偏移量匹配速度,3个左右的关键字复合检索能够在1秒内完成匹配(要求操作系统有足够大的缓存)。
目前实现的一些局限和优势:
0 中文检索速度足够,准确度比Lucene高(如果有高手能够解决这个问题,我会很高兴的废弃掉这些类的)
1 合适于中文,不适用英文文本
2 全文检索索引文件与原始文本文件的大小大约为2:3-3:4之间,300M大小,比Lucene大约多30M。
3 索引文件的构建时间长,400M大约需要3小时,同时由于如果任何文本文件更新,都需要重新构建索引文件,
因此不合适要经常变化的文本索引。
全文检索代码示例(TestFullTextQuery.java):
File storeDir = new File("C:\\temp\\fulltext\\index");
StoreSearcher searcher = new StoreSearcher(storeDir);
String str = "大?藏 & 阿难"; //同时出现 "大?藏" 和 "阿难", ?代表任意字符
searcher.queryBegin(str, true);
while(true){
StoreSearcherResult ssr = searcher.getNextQueryResult();
if ( ssr == null ){
break;
}
System.out.println("ID "+ssr.docId+":"+ssr.matchedCount);
}
searcher.queryEnd();
searcher.close();
运行结果
ID T01n0001.TXT:320
ID T01n0002.TXT:3
ID T01n0004.TXT:2
ID T01n0005.TXT:202
ID T01n0006.TXT:131
....
附:全文检索表达式举例
关键字中间可以出现?,表明匹配任意字符。
运算符名称:运算符字符
AND:&
OR:,
BEFORE:*
NEAR:+
NOT:-
表达式举例:
(KEY1 <AND|OR|BEFORE|NEAR> KEY2) & (NOT KEY3)
KEY1 KEY2 (关键字之间无运算符假设为AND)
附:全文检索文件格式信息
DocInfoStore(文档信息)
--HEAD--
DocCount:Integer 文档数目
--DOC HEAD(PER DOC)--
DocSeq: Integer 文档顺序号,内部使用
DocId: Char[128] 文档唯一ID,字符串格式
DocSepOfs: Integer 文档分隔符数组的Ofs
--DOC SEP OFS(PER DOC)--
DocOfs: ArrayOfInteger 文档分隔数组
WordInfoStore(每个汉字信息)
--HEAD--
WordCount:Integer 汉字数
--WORD IDX(Per Word)--
WordChar:Integer 汉字的Unicode值
WordInfoOfs:Integer 汉字信息在文件中的偏移量
WordInfoSize:Integer 汉字信息大小
--WORD INFO(Per Word)--
DocCount: 汉字出现的文档数
DocSeq(Per Doc): 每个文档的顺序号
WordInDocs:ArrayOfInteger 每个文档中出现的汉字的偏移数组,从小到大排列
源文件及CLASS下载地址:
http://www.blogjava.net/Files/zhugf000/foreader2_ftsearch.zip
Feedback
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2007-07-31 08:52 by
看一下。。。。。。
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2007-07-31 10:33 by
用正则表达式啊
# re: 中文全文检索的实现以及一些经验(Java)[未登录] 回复 更多评论
2007-07-31 10:59 by
说起来,Lucene的性能似乎不行啊(我没测试过啊,只是网上资料说明)。似乎千万级别就比较慢了。前段日子用Lucene开发了个站内搜索(数据量大概在几百万吧),感觉无论是搜索(其实还好,在可接收范围内)和索引都有点慢。有没更好的实现啊?那些真正的能承受较大压力的搜索都是怎么开发的?谁知道?
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2007-07-31 14:59 by
都是的分布式的,索引和爬取基本上都是用的C++,WEB层用的是PHP,这是完美的结合!
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2007-07-31 17:08 by
这个有技术含量.
# re: 中文全文检索的实现以及一些经验(Java)[未登录] 回复 更多评论
2007-08-01 14:12 by
笨笨啊,我有点迷茫。能给解答一下吗?
公司的站内搜索OK了,但领导让我继续研究研究搜索,但我不知道该继续去研究什么好了。
中文分词?目前使用的模块(JE)还可以,如果自己研发需要不少时间,还有词库问题。
爬虫?我们是站内搜索,虽然头说站外也是个方向,但很不明确,我对没有明确需求的东西实在不感兴趣。
分布式?目前的量还没必要(几百万),差的很远的,而且如果一直站内搜索的话也很难用上。
缓冲?这个很有用,但目前实在没有太好的想法。
目前站内搜索的状况就是正常运行,没什么错误,也不知道该改些什么。很迷茫。(还有个项目相反,能正常运行,但我还有很多想法,但领导说我在那个项目浪费太多时间了,不许我再做了,能运行就行。-_-!)
最近很怪,我对搜索的研究很迷茫,对用户的需求倒是很感兴趣。我一直在思考自己的东西最终能给用户带来什么,如何让用户更加方便的使用。
嗯。。。就是很迷茫,有啥好的建议吗?
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2007-08-02 14:04 by
用lucene检索的时候,结果少的原因,应该是,你查询的时候用的分词器不对。
在查询之前先把每个字直接加一个空格。例如:“中文检索”-》“中 文 检 索”。
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2008-06-18 15:40 by
很好的东西啊 呵呵 可惜缺少些jar
能不能送我啊 litao1258@126.com
多谢
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2008-07-01 15:12 by
东西已经收到,不胜感激!
# re: 中文全文检索的实现以及一些经验(Java) 回复 更多评论
2008-08-11 11:46 by
你好,笨笨,我刚刚研究lucene,现在面临的问题也是中文的全文检索,
我的问题正好和你相反,我返回的数据太多了。
比如搜索的keyword是[高考]会被拆分为[高][考]两个字进行检索。
这样的话检索大量数据的时候就会很慢,而且我做了关键字的高亮显示
这样一来,比如标题为【2008年北京考区高考状元】那么被高亮后为
2008年北京[考]区[高][考]状元,这样看起来很不好,怎么样可以按着【词】来
建立索引呢,然后按着【词】进行检索并高亮,头疼的问题,可以和您讨论一下嘛?
其他的朋友也欢迎讨论。希望您能联系我一下,QQ396615834 MSN wind_1121@hotmail.com 十分感谢。