1, 提高建索引
![](/icons/51928de.gif)
速度
/**
* 在IndexWriter中有
![](/icons/51928yi.gif)
个MERGE_FACTOR参数可以帮助你在构造索引器后根据应用环境
![](/icons/51928de.gif)
情况充分利用内存减少文件
![](/icons/51928de.gif)
操作
![](/icons/51928dou2.gif)
根据我
![](/icons/51928de.gif)
使用经验:缺省Indexer是每20条记录索引后写入
![](/icons/51928yi.gif)
次
![](/icons/51928dou.gif)
每将MERGE_FACTOR增加50倍
![](/icons/51928dou.gif)
索引速度可以提高1倍左右
![](/icons/51928dou2.gif)
*/
indexWriter.
![](/icons/51928set.gif)
MergeFactor(1000);
2, 排序
« 从 汉化 到 国际化 | (回到Blog入口)|(回到首页) | Resin学习笔记 »
Lucene:基于Java
![](/icons/51928de.gif)
全文检索引擎介绍
作者:车东 发表于:2002-08-06 18:08 最后更新于:2007-04-12 11:04
版权声明:可以任意转载
![](/icons/51928dou.gif)
转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
![](/icons/51928dou2.gif)
http://www.chedong.com/tech/lucene.html
--------------------------------------------------------------------------------
Lucene是
![](/icons/51928yi.gif)
个基于Java
![](/icons/51928de.gif)
全文索引工具包
![](/icons/51928dou2.gif)
基于Java
![](/icons/51928de.gif)
全文索引引擎Lucene介绍:有关作者和Lucene
![](/icons/51928de.gif)
历史
全文检索
![](/icons/51928de.gif)
实现:Luene全文索引和数据库索引
![](/icons/51928de.gif)
比较
中文切分词机制介绍:基于词库和自动切分词算法
![](/icons/51928de.gif)
比较
具体
![](/icons/51928de.gif)
安装和使用介绍:系统结构介绍和演示
Hacking Lucene:简化
![](/icons/51928de.gif)
查询分析器
![](/icons/51928dou.gif)
删除
![](/icons/51928de.gif)
实现
![](/icons/51928dou.gif)
定制
![](/icons/51928de.gif)
排序
![](/icons/51928dou.gif)
应用接口
![](/icons/51928de.gif)
扩展
从Lucene我们还可以学到什么
基于Java
![](/icons/51928de.gif)
全文索引/检索引擎——Lucene
Lucene不是
![](/icons/51928yi.gif)
个完整
![](/icons/51928de.gif)
全文索引应用
![](/icons/51928dou.gif)
而是是
![](/icons/51928yi.gif)
个用Java写
![](/icons/51928de.gif)
全文索引引擎工具包
![](/icons/51928dou.gif)
它可以方便
![](/icons/51928de.gif)
嵌入到各种应用中实现针对应用
![](/icons/51928de.gif)
全文索引/检索功能
![](/icons/51928dou2.gif)
Lucene
![](/icons/51928de.gif)
作者:Lucene
![](/icons/51928de.gif)
贡献者Doug Cutting是
![](/icons/51928yi.gif)
位资深全文索引/检索专家
![](/icons/51928dou.gif)
曾经是V-Twin搜索引擎(Apple
![](/icons/51928de.gif)
Copland操作系统
![](/icons/51928de.gif)
成就的
![](/icons/51928yi.gif)
)
![](/icons/51928de.gif)
主要开发者
![](/icons/51928dou.gif)
后在Excite担任高级系统架构设计师
![](/icons/51928dou.gif)
目前从事于
![](/icons/51928yi.gif)
些INTERNET底层架构
![](/icons/51928de.gif)
研究
![](/icons/51928dou2.gif)
他贡献出
![](/icons/51928de.gif)
Lucene
![](/icons/51928de.gif)
目标是为各种中小型应用
![](/icons/51928chengxu.gif)
加入全文检索功能
![](/icons/51928dou2.gif)
Lucene
![](/icons/51928de.gif)
发展历程:早先发布在作者自己
![](/icons/51928de.gif)
www.lucene.com
![](/icons/51928dou.gif)
后来发布在SourceForge
![](/icons/51928dou.gif)
2001年年底成为APACHE基金会jakarta
![](/icons/51928de.gif)
![](/icons/51928yi.gif)
个子项目:http://jakarta.apache.org/lucene/
已经有很多Java项目都使用了Lucene作为其后台
![](/icons/51928de.gif)
全文索引引擎
![](/icons/51928dou.gif)
比较著名
![](/icons/51928de.gif)
有:
Jive:WEB论坛系统;
Eyebrows:邮件列表HTML归档/浏览/查询系统
![](/icons/51928dou.gif)
本文
![](/icons/51928de.gif)
主要参考文档“TheLucene search engine: Powerful, flexible, and free”作者就是EyeBrows系统
![](/icons/51928de.gif)
主要开发者的
![](/icons/51928yi.gif)
![](/icons/51928dou.gif)
而EyeBrows已经成为目前APACHE项目
![](/icons/51928de.gif)
主要邮件列表归档系统
![](/icons/51928dou2.gif)
Cocoon:基于XML
![](/icons/51928de.gif)
web发布框架
![](/icons/51928dou.gif)
全文检索部分使用了Lucene
Eclipse:基于Java
![](/icons/51928de.gif)
开放开发平台
![](/icons/51928dou.gif)
帮助部分
![](/icons/51928de.gif)
全文索引使用了Lucene
对于中文用户来说
![](/icons/51928dou.gif)
最关心
![](/icons/51928de.gif)
问题是其是否支持中文
![](/icons/51928de.gif)
全文检索
![](/icons/51928dou2.gif)
但通过后面对于Lucene
![](/icons/51928de.gif)
结构
![](/icons/51928de.gif)
介绍
![](/icons/51928dou.gif)
你会了解到由于Lucene良好架构设计
![](/icons/51928dou.gif)
对中文
![](/icons/51928de.gif)
支持只需对其语言词法分析接口进行扩展就能实现对中文检索
![](/icons/51928de.gif)
支持
![](/icons/51928dou2.gif)
全文检索
![](/icons/51928de.gif)
实现机制
Lucene
![](/icons/51928de.gif)
API接口设计
![](/icons/51928de.gif)
比较通用
![](/icons/51928dou.gif)
输入输出结构都很像数据库
![](/icons/51928de.gif)
表
![](/icons/51928dd.gif)
>记录
![](/icons/51928dd.gif)
>字段
![](/icons/51928dou.gif)
所以很多传统
![](/icons/51928de.gif)
应用
![](/icons/51928de.gif)
文件、数据库等都可以比较方便
![](/icons/51928de.gif)
映射到Lucene
![](/icons/51928de.gif)
存储结构/接口中
![](/icons/51928dou2.gif)
总体上看:可以先把Lucene当成
![](/icons/51928yi.gif)
个支持全文索引
![](/icons/51928de.gif)
数据库系统
![](/icons/51928dou2.gif)
比较
![](/icons/51928yi.gif)
下Lucene和数据库:
Lucene 数据库
索引数据源:doc(field1,field2...) doc(field1,field2...) indexer / _____________ | Lucene Index| -------------- / searcher 结果输出:Hits(doc(field1,field2) doc(field1...)) 索引数据源:record(field1,field2...) record(field1..) SQL: insert/ _____________ | DB Index | ------------- / SQL: select 结果输出:results(record(field1,field2..) record(field1...))
Document:
![](/icons/51928yi.gif)
个需要进行索引
![](/icons/51928de.gif)
“单元”
![](/icons/51928yi.gif)
个Document由多个字段组成 Record:记录
![](/icons/51928dou.gif)
包含多个字段
Field:字段 Field:字段
Hits:查询结果集
![](/icons/51928dou.gif)
由匹配
![](/icons/51928de.gif)
Document组成 RecordSet:查询结果集
![](/icons/51928dou.gif)
由多个Record组成
全文检索 ≠ like "%keyword%"
通常比较厚
![](/icons/51928de.gif)
书籍后面常常附关键词索引表(比如:北京:12, 34页
![](/icons/51928dou.gif)
上海:3,77页……)
![](/icons/51928dou.gif)
它能够帮助读者比较快地找到相关内容
![](/icons/51928de.gif)
页码
![](/icons/51928dou2.gif)
而数据库索引能够大大提高查询
![](/icons/51928de.gif)
速度原理也是
![](/icons/51928yi.gif)
样
![](/icons/51928dou.gif)
想像
![](/icons/51928yi.gif)
下通过书后面
![](/icons/51928de.gif)
索引查找
![](/icons/51928de.gif)
速度要比
![](/icons/51928yi.gif)
页
![](/icons/51928yi.gif)
页地翻内容高多少倍……而索引的所以效率高
![](/icons/51928dou.gif)
另外
![](/icons/51928yi.gif)
个原因是它是排好序
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
对于检索系统来说核心是
![](/icons/51928yi.gif)
个排序问题
![](/icons/51928dou2.gif)
由于数据库索引不是为全文索引设计
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
因此
![](/icons/51928dou.gif)
使用like "%keyword%"时
![](/icons/51928dou.gif)
数据库索引是不起作用
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
在使用like查询时
![](/icons/51928dou.gif)
搜索过程又变成类似于
![](/icons/51928yi.gif)
页页翻书
![](/icons/51928de.gif)
遍历过程了
![](/icons/51928dou.gif)
所以对于含有模糊查询
![](/icons/51928de.gif)
数据库服务来说
![](/icons/51928dou.gif)
LIKE对性能
![](/icons/51928de.gif)
危害是极大
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
如果是需要对多个关键词进行模糊匹配:like"%keyword1%" and like "%keyword2%" ...其效率也就可想而知了
![](/icons/51928dou2.gif)
所以建立
![](/icons/51928yi.gif)
个高效检索系统
![](/icons/51928de.gif)
关键是建立
![](/icons/51928yi.gif)
个类似于科技索引
![](/icons/51928yi.gif)
样
![](/icons/51928de.gif)
反向索引机制
![](/icons/51928dou.gif)
将数据源(比如多篇文章)排序顺序存储
![](/icons/51928de.gif)
同时
![](/icons/51928dou.gif)
有另外
![](/icons/51928yi.gif)
个排好序
![](/icons/51928de.gif)
关键词列表
![](/icons/51928dou.gif)
用于存储关键词
![](/icons/51928dd.gif)
>文章映射关系
![](/icons/51928dou.gif)
利用这样
![](/icons/51928de.gif)
映射关系索引:[关键词
![](/icons/51928dd.gif)
>出现关键词
![](/icons/51928de.gif)
文章编号
![](/icons/51928dou.gif)
出现次数(甚至包括位置:起始偏移量
![](/icons/51928dou.gif)
结束偏移量)
![](/icons/51928dou.gif)
出现频率]
![](/icons/51928dou.gif)
检索过程就是把模糊查询变成多个可以利用索引
![](/icons/51928de.gif)
精确查询
![](/icons/51928de.gif)
逻辑组合
![](/icons/51928de.gif)
过程
![](/icons/51928dou2.gif)
从而大大提高了多关键词查询
![](/icons/51928de.gif)
效率
![](/icons/51928dou.gif)
所以
![](/icons/51928dou.gif)
全文检索问题归结到最后是
![](/icons/51928yi.gif)
个排序问题
![](/icons/51928dou2.gif)
由此可以看出模糊查询相对数据库
![](/icons/51928de.gif)
精确查询是
![](/icons/51928yi.gif)
个非常不确定
![](/icons/51928de.gif)
问题
![](/icons/51928dou.gif)
这也是大部分数据库对全文检索支持有限
![](/icons/51928de.gif)
原因
![](/icons/51928dou2.gif)
Lucene最核心
![](/icons/51928de.gif)
特征是通过特殊
![](/icons/51928de.gif)
索引结构实现了传统数据库不擅长
![](/icons/51928de.gif)
全文索引机制
![](/icons/51928dou.gif)
并提供了扩展接口
![](/icons/51928dou.gif)
以方便针对区别应用
![](/icons/51928de.gif)
定制
![](/icons/51928dou2.gif)
可以通过
![](/icons/51928yi.gif)
下表格对比
![](/icons/51928yi.gif)
下数据库
![](/icons/51928de.gif)
模糊查询:
Lucene全文索引引擎 数据库
索引 将数据源中
![](/icons/51928de.gif)
数据都通过全文索引
![](/icons/51928yi.gif)
![](/icons/51928yi.gif)
建立反向索引 对于LIKE查询来说
![](/icons/51928dou.gif)
数据传统
![](/icons/51928de.gif)
索引是根本用不上
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
数据需要逐个便利记录进行GREP式
![](/icons/51928de.gif)
模糊匹配
![](/icons/51928dou.gif)
比有索引
![](/icons/51928de.gif)
搜索速度要有多个数量级
![](/icons/51928de.gif)
下降
![](/icons/51928dou2.gif)
匹配效果 通过词元(term)进行匹配
![](/icons/51928dou.gif)
通过语言分析接口
![](/icons/51928de.gif)
实现
![](/icons/51928dou.gif)
可以实现对中文等非英语
![](/icons/51928de.gif)
支持
![](/icons/51928dou2.gif)
使用:like "%net%" 会把netherlands也匹配出来
![](/icons/51928dou.gif)
多个关键词
![](/icons/51928de.gif)
模糊匹配:使用like "%com%net%":就不能匹配词序颠倒
![](/icons/51928de.gif)
xxx.net..xxx.com
匹配度 有匹配度算法
![](/icons/51928dou.gif)
将匹配程度(相似度)比较高
![](/icons/51928de.gif)
结果排在前面
![](/icons/51928dou2.gif)
没有匹配程度
![](/icons/51928de.gif)
控制:比如有记录中net出现5词和出现1次
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
结果是
![](/icons/51928yi.gif)
样
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
结果输出 通过特别
![](/icons/51928de.gif)
算法
![](/icons/51928dou.gif)
将最匹配度最高
![](/icons/51928de.gif)
头100条结果输出
![](/icons/51928dou.gif)
结果集是缓冲式
![](/icons/51928de.gif)
小批量读取
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
返回所有
![](/icons/51928de.gif)
结果集
![](/icons/51928dou.gif)
在匹配条目非常多
![](/icons/51928de.gif)
时候(比如上万条)需要大量
![](/icons/51928de.gif)
内存存放这些临时结果集
![](/icons/51928dou2.gif)
可定制性 通过区别
![](/icons/51928de.gif)
语言分析接口实现
![](/icons/51928dou.gif)
可以方便
![](/icons/51928de.gif)
定制出符合应用需要
![](/icons/51928de.gif)
索引规则(包括对中文
![](/icons/51928de.gif)
支持) 没有接口或接口复杂
![](/icons/51928dou.gif)
无法定制
结论 高负载
![](/icons/51928de.gif)
模糊查询应用
![](/icons/51928dou.gif)
需要负责
![](/icons/51928de.gif)
模糊查询
![](/icons/51928de.gif)
规则
![](/icons/51928dou.gif)
索引
![](/icons/51928de.gif)
资料量比较大 使用率低
![](/icons/51928dou.gif)
模糊匹配规则简单或者需要模糊查询
![](/icons/51928de.gif)
资料量少
全文检索和数据库应用最大
![](/icons/51928de.gif)
区别在于:让最相关
![](/icons/51928de.gif)
头100条结果满足98%以上用户
![](/icons/51928de.gif)
需求
Lucene
![](/icons/51928de.gif)
创新的处:
大部分
![](/icons/51928de.gif)
搜索(数据库)引擎都是用B树结构来维护索引
![](/icons/51928dou.gif)
索引
![](/icons/51928de.gif)
更新会导致大量
![](/icons/51928de.gif)
IO操作
![](/icons/51928dou.gif)
Lucene在实现中
![](/icons/51928dou.gif)
对此稍微有所改进:不是维护
![](/icons/51928yi.gif)
个索引文件
![](/icons/51928dou.gif)
而是在扩展索引
![](/icons/51928de.gif)
时候不断创建新
![](/icons/51928de.gif)
索引文件
![](/icons/51928dou.gif)
然后定期
![](/icons/51928de.gif)
把这些新
![](/icons/51928de.gif)
小索引文件合并到原先
![](/icons/51928de.gif)
大索引中(针对区别
![](/icons/51928de.gif)
更新策略
![](/icons/51928dou.gif)
批次
![](/icons/51928de.gif)
大小可以调整)
![](/icons/51928dou.gif)
这样在不影响检索
![](/icons/51928de.gif)
效率
![](/icons/51928de.gif)
前提下
![](/icons/51928dou.gif)
提高了索引
![](/icons/51928de.gif)
效率
![](/icons/51928dou2.gif)
Lucene和其他
![](/icons/51928yi.gif)
些全文检索系统/应用
![](/icons/51928de.gif)
比较:
Lucene 其他开源全文检索系统
增量索引和批量索引 可以进行增量
![](/icons/51928de.gif)
索引(Append)
![](/icons/51928dou.gif)
可以对于大量数据进行批量索引
![](/icons/51928dou.gif)
并且接口设计用于优化批量索引和小批量
![](/icons/51928de.gif)
增量索引
![](/icons/51928dou2.gif)
很多系统只支持批量
![](/icons/51928de.gif)
索引
![](/icons/51928dou.gif)
有时数据源有
![](/icons/51928yi.gif)
点增加也需要重建索引
![](/icons/51928dou2.gif)
数据源 Lucene没有定义具体
![](/icons/51928de.gif)
数据源
![](/icons/51928dou.gif)
而是
![](/icons/51928yi.gif)
个文档
![](/icons/51928de.gif)
结构
![](/icons/51928dou.gif)
因此可以非常灵活
![](/icons/51928de.gif)
适应各种应用(只要前端有合适
![](/icons/51928de.gif)
转换器把数据源转换成相应结构)
![](/icons/51928dou.gif)
很多系统只针对网页
![](/icons/51928dou.gif)
缺乏其他格式文档
![](/icons/51928de.gif)
灵活性
![](/icons/51928dou2.gif)
索引内容抓取 Lucene
![](/icons/51928de.gif)
文档是由多个字段组成
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
甚至可以控制那些字段需要进行索引
![](/icons/51928dou.gif)
那些字段不需要索引
![](/icons/51928dou.gif)
近
![](/icons/51928yi.gif)
步索引
![](/icons/51928de.gif)
字段也分为需要分词和不需要分词
![](/icons/51928de.gif)
类型:
需要进行分词
![](/icons/51928de.gif)
索引
![](/icons/51928dou.gif)
比如:标题
![](/icons/51928dou.gif)
文章内容字段
不需要进行分词
![](/icons/51928de.gif)
索引
![](/icons/51928dou.gif)
比如:作者/日期字段 缺乏通用性
![](/icons/51928dou.gif)
往往将文档整个索引了
语言分析 通过语言分析器
![](/icons/51928de.gif)
区别扩展实现:
可以过滤掉不需要
![](/icons/51928de.gif)
词:an the of 等
![](/icons/51928dou.gif)
西文语法分析:将jumps jumped jumper都归结成jump进行索引/检索
非英文支持:对亚洲语言
![](/icons/51928dou.gif)
阿拉伯语言
![](/icons/51928de.gif)
索引支持 缺乏通用接口实现
查询分析 通过查询分析接口
![](/icons/51928de.gif)
实现
![](/icons/51928dou.gif)
可以定制自己
![](/icons/51928de.gif)
查询语法规则:
比如: 多个关键词的间
![](/icons/51928de.gif)
+ - and or关系等
并发访问 能够支持多用户
![](/icons/51928de.gif)
使用
有关亚洲语言
![](/icons/51928de.gif)
![](/icons/51928de.gif)
切分词问题(Word Segment)
对于中文来说
![](/icons/51928dou.gif)
全文索引首先还要解决
![](/icons/51928yi.gif)
个语言分析
![](/icons/51928de.gif)
问题
![](/icons/51928dou.gif)
对于英文来说
![](/icons/51928dou.gif)
语句中单词的间是天然通过空格分开
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
但亚洲语言
![](/icons/51928de.gif)
中日韩文语句中
![](/icons/51928de.gif)
字是
![](/icons/51928yi.gif)
个字挨
![](/icons/51928yi.gif)
个
![](/icons/51928dou.gif)
所有
![](/icons/51928dou.gif)
首先要把语句中按“词”进行索引
![](/icons/51928de.gif)
话
![](/icons/51928dou.gif)
这个词如何切分出来就是
![](/icons/51928yi.gif)
个很大
![](/icons/51928de.gif)
问题
![](/icons/51928dou2.gif)
首先
![](/icons/51928dou.gif)
肯定不能用单个
![](/icons/51928zifu.gif)
作(si-gram)为索引单元
![](/icons/51928dou.gif)
否则查“上海”时
![](/icons/51928dou.gif)
不能让含有“海上”也匹配
![](/icons/51928dou2.gif)
但
![](/icons/51928yi.gif)
句话:“北京天安门”
![](/icons/51928dou.gif)
计算机如何按照中文
![](/icons/51928de.gif)
语言习惯进行切分呢?
“北京 天安门” 还是“北 京 天安门”?让计算机能够按照语言习惯进行切分
![](/icons/51928dou.gif)
往往需要机器有
![](/icons/51928yi.gif)
个比较丰富
![](/icons/51928de.gif)
词库才能够比较准确
![](/icons/51928de.gif)
识别出语句中
![](/icons/51928de.gif)
单词
![](/icons/51928dou2.gif)
另外
![](/icons/51928yi.gif)
个解决
![](/icons/51928de.gif)
办法是采用自动切分算法:将单词按照2元语法(bigram)方式切分出来
![](/icons/51928dou.gif)
比如:
"北京天安门"
![](/icons/51928dd.gif)
> "北京 京天 天安 安门"
![](/icons/51928dou2.gif)
这样
![](/icons/51928dou.gif)
在查询
![](/icons/51928de.gif)
时候
![](/icons/51928dou.gif)
无论是查询"北京" 还是查询"天安门"
![](/icons/51928dou.gif)
将查询词组按同样
![](/icons/51928de.gif)
规则进行切分:"北京"
![](/icons/51928dou.gif)
"天安安门"
![](/icons/51928dou.gif)
多个关键词的间按和"and"
![](/icons/51928de.gif)
关系组合
![](/icons/51928dou.gif)
同样能够正确地映射到相应
![](/icons/51928de.gif)
索引中
![](/icons/51928dou2.gif)
这种方式对于其他亚洲语言:韩文
![](/icons/51928dou.gif)
日文都是通用
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
基于自动切分
![](/icons/51928de.gif)
最大优点是没有词表维护成本
![](/icons/51928dou.gif)
实现简单
![](/icons/51928dou.gif)
缺点是索引效率低
![](/icons/51928dou.gif)
但对于中小型应用来说
![](/icons/51928dou.gif)
基于2元语法
![](/icons/51928de.gif)
切分还是够用
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
基于2元切分后
![](/icons/51928de.gif)
索引
![](/icons/51928yi.gif)
般大小和源文件差不多
![](/icons/51928dou.gif)
而对于英文
![](/icons/51928dou.gif)
索引文件
![](/icons/51928yi.gif)
般只有原文件
![](/icons/51928de.gif)
30%-40%区别
![](/icons/51928dou.gif)
自动切分 词表切分
实现 实现非常简单 实现复杂
查询 增加了查询分析
![](/icons/51928de.gif)
复杂程度
![](/icons/51928dou.gif)
适于实现比较复杂
![](/icons/51928de.gif)
查询语法规则
存储效率 索引冗余大
![](/icons/51928dou.gif)
索引几乎和原文
![](/icons/51928yi.gif)
样大 索引效率高
![](/icons/51928dou.gif)
为原文大小
![](/icons/51928de.gif)
30%左右
维护成本 无词表维护成本 词表维护成本非常高:中日韩等语言需要分别维护
![](/icons/51928dou2.gif)
还需要包括词频统计等内容
适用领域 嵌入式系统:运行环境资源有限
分布式系统:无词表同步问题
多语言环境:无词表维护成本 对查询和存储效率要求高
![](/icons/51928de.gif)
专业搜索引擎
目前比较大
![](/icons/51928de.gif)
搜索引擎
![](/icons/51928de.gif)
语言分析算法
![](/icons/51928yi.gif)
般是基于以上2个机制
![](/icons/51928de.gif)
结合
![](/icons/51928dou2.gif)
有关中文
![](/icons/51928de.gif)
语言分析算法
![](/icons/51928dou.gif)
大家可以在Google查关键词"wordsegment search"能找到更多相关
![](/icons/51928de.gif)
资料
![](/icons/51928dou2.gif)
安装和使用
下载:http://jakarta.apache.org/lucene/
注意:Lucene中
![](/icons/51928de.gif)
![](/icons/51928yi.gif)
些比较复杂
![](/icons/51928de.gif)
词法分析是用JavaCC生成
![](/icons/51928de.gif)
(JavaCC:JavaCompilerCompiler
![](/icons/51928dou.gif)
纯Java
![](/icons/51928de.gif)
词法分析生成器)
![](/icons/51928dou.gif)
所以如果从源代码编译或需要修改其中
![](/icons/51928de.gif)
QueryParser、定制自己
![](/icons/51928de.gif)
词法分析器
![](/icons/51928dou.gif)
还需要从http://javacc.dev.java.net/下载javacc
![](/icons/51928dou2.gif)
lucene
![](/icons/51928de.gif)
组成结构:对于外部应用来说索引模块(index)和检索模块(search)是主要
![](/icons/51928de.gif)
外部应用入口
org.apache.Lucene.search/ 搜索入口
org.apache.Lucene.index/ 索引入口
org.apache.Lucene.analysis/ 语言分析器
org.apache.Lucene.queryParser/ 查询分析器
org.apache.Lucene.document/ 存储结构
org.apache.Lucene.store/ 底层IO/存储结构
org.apache.Lucene.util/
![](/icons/51928yi.gif)
些公用
![](/icons/51928de.gif)
数据结构
简单
![](/icons/51928de.gif)
例子演示
![](/icons/51928yi.gif)
下Lucene
![](/icons/51928de.gif)
使用思路方法:
索引过程:从命令行读取文件名(多个)
![](/icons/51928dou.gif)
将文件分路径(path字段)和内容(body字段)2个字段进行存储
![](/icons/51928dou.gif)
并对内容进行全文索引:索引
![](/icons/51928de.gif)
单位是Document对象
![](/icons/51928dou.gif)
每个Document对象包含多个字段Field对象
![](/icons/51928dou.gif)
针对区别
![](/icons/51928de.gif)
字段属性和数据输出
![](/icons/51928de.gif)
需求
![](/icons/51928dou.gif)
对字段还可以选择区别
![](/icons/51928de.gif)
索引/存储字段规则
![](/icons/51928dou.gif)
列表如下: 思路方法 切词 索引 存储 用途
Field.Text(String name, String value) Yes Yes Yes 切分词索引并存储
![](/icons/51928dou.gif)
比如:标题
![](/icons/51928dou.gif)
内容字段
Field.Text(String name, Reader value) Yes Yes No 切分词索引不存储
![](/icons/51928dou.gif)
比如:META信息
![](/icons/51928dou.gif)
不用于返回显示
![](/icons/51928dou.gif)
但需要进行检索内容
Field.Keyword(String name, String value) No Yes Yes 不切分索引并存储
![](/icons/51928dou.gif)
比如:日期字段
Field.UnIndexed(String name, String value) No No Yes 不索引
![](/icons/51928dou.gif)
只存储
![](/icons/51928dou.gif)
比如:文件路径
Field.UnStored(String name, String value) Yes Yes No 只全文索引
![](/icons/51928dou.gif)
不存储
public
![](/icons/51928class.gif)
IndexFiles { //使用思路方法:: IndexFiles [索引输出目录] [索引
![](/icons/51928de.gif)
文件列表] ... public
![](/icons/51928static.gif)
void
![](/icons/51928main.gif)
(String
![](/icons/51928zhk2.gif)
args) throws Exception { String indexPath = args[0]; IndexWriter writer; //用指定
![](/icons/51928de.gif)
语言分析器构造
![](/icons/51928yi.gif)
个新
![](/icons/51928de.gif)
写索引器(第3个参数表示是否为追加索引) writer =
![](/icons/51928new.gif)
IndexWriter(indexPath,
![](/icons/51928new.gif)
SimpleAnalyzer
![](/icons/51928kh.gif)
, false); for (
![](/icons/51928int.gif)
i=1; i<args.length; i
![](/icons/51928jiajia.gif)
) {
![](/icons/51928System.gif)
.out.pr
![](/icons/51928int.gif)
ln("Indexing file " + args); InputStream is =
![](/icons/51928new.gif)
FileInputStream(args); //构造包含2个字段Field
![](/icons/51928de.gif)
Document对象 //
![](/icons/51928yi.gif)
个是路径path字段
![](/icons/51928dou.gif)
不索引
![](/icons/51928dou.gif)
只存储 //
![](/icons/51928yi.gif)
个是内容body字段
![](/icons/51928dou.gif)
进行全文索引
![](/icons/51928dou.gif)
并存储 Document doc =
![](/icons/51928new.gif)
Document
![](/icons/51928kh.gif)
; doc.add(Field.UnIndexed("path", args)); doc.add(Field.Text("body", (Reader)
![](/icons/51928new.gif)
InputStreamReader(is))); //将文档写入索引 writer.addDocument(doc); is.close
![](/icons/51928kh.gif)
; }; //关闭写索引器 writer.close
![](/icons/51928kh.gif)
; }} 索引过程中可以看到:
语言分析器提供了抽象
![](/icons/51928de.gif)
接口
![](/icons/51928dou.gif)
因此语言分析(Analyser)是可以定制
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
虽然lucene缺省提供了2个比较通用
![](/icons/51928de.gif)
分析器SimpleAnalyser和StandardAnalyser
![](/icons/51928dou.gif)
这2个分析器缺省都不支持中文
![](/icons/51928dou.gif)
所以要加入对中文语言
![](/icons/51928de.gif)
切分规则
![](/icons/51928dou.gif)
需要修改这2个分析器
![](/icons/51928dou2.gif)
Lucene并没有规定数据源
![](/icons/51928de.gif)
格式
![](/icons/51928dou.gif)
而只提供了
![](/icons/51928yi.gif)
个通用
![](/icons/51928de.gif)
结构(Document对象)来接受索引
![](/icons/51928de.gif)
输入
![](/icons/51928dou.gif)
因此输入
![](/icons/51928de.gif)
数据源可以是:数据库
![](/icons/51928dou.gif)
WORD文档
![](/icons/51928dou.gif)
PDF文档
![](/icons/51928dou.gif)
HTML文档……只要能够设计相应
![](/icons/51928de.gif)
解析转换器将数据源构造成成Docuement对象即可进行索引
![](/icons/51928dou2.gif)
对于大批量
![](/icons/51928de.gif)
数据索引
![](/icons/51928dou.gif)
还可以通过调整IndexerWrite
![](/icons/51928de.gif)
文件合并频率属性(mergeFactor)来提高批量索引
![](/icons/51928de.gif)
效率
![](/icons/51928dou2.gif)
检索过程和结果显示:
搜索结果返回
![](/icons/51928de.gif)
是Hits对象
![](/icons/51928dou.gif)
可以通过它再访问Document
![](/icons/51928dd.gif)
>Field中
![](/icons/51928de.gif)
内容
![](/icons/51928dou2.gif)
假设根据body字段进行全文检索
![](/icons/51928dou.gif)
可以将查询结果
![](/icons/51928de.gif)
path字段和相应查询
![](/icons/51928de.gif)
匹配度(score)打印出来
![](/icons/51928dou.gif)
public
![](/icons/51928class.gif)
Search { public
![](/icons/51928static.gif)
void
![](/icons/51928main.gif)
(String
![](/icons/51928zhk2.gif)
args) throws Exception { String indexPath = args[0], queryString = args[1]; //指向索引目录
![](/icons/51928de.gif)
搜索器 Searcher searcher =
![](/icons/51928new.gif)
IndexSearcher(indexPath); //查询解析器:使用和索引同样
![](/icons/51928de.gif)
语言分析器 Query query = QueryParser.parse(queryString, "body",
![](/icons/51928new.gif)
SimpleAnalyzer
![](/icons/51928kh.gif)
); //搜索结果使用Hits存储 Hits hits = searcher.search(query); //通过hits可以访问到相应字段
![](/icons/51928de.gif)
数据和查询
![](/icons/51928de.gif)
匹配度 for (
![](/icons/51928int.gif)
i=0; i<hits.length
![](/icons/51928kh.gif)
; i
![](/icons/51928jiajia.gif)
) {
![](/icons/51928System.gif)
.out.pr
![](/icons/51928int.gif)
ln(hits.doc(i).get("path") + "; Score: " + hits.score(i)); }; }}在整个检索过程中
![](/icons/51928dou.gif)
语言分析器
![](/icons/51928dou.gif)
查询分析器
![](/icons/51928dou.gif)
甚至搜索器(Searcher)都是提供了抽象
![](/icons/51928de.gif)
接口
![](/icons/51928dou.gif)
可以根据需要进行定制
![](/icons/51928dou2.gif)
Hacking Lucene
简化
![](/icons/51928de.gif)
查询分析器
个人感觉lucene成为JAKARTA项目后
![](/icons/51928dou.gif)
画在了太多
![](/icons/51928de.gif)
时间用于调试日趋复杂QueryParser
![](/icons/51928dou.gif)
而其中大部分是大多数用户并不很熟悉
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
目前LUCENE支持
![](/icons/51928de.gif)
语法:
Query ::= ( Clause )*
Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")")
中间
![](/icons/51928de.gif)
逻辑包括:and or + - &&||等符号
![](/icons/51928dou.gif)
而且还有"短语查询"和针对西文
![](/icons/51928de.gif)
前缀/模糊查询等
![](/icons/51928dou.gif)
个人感觉对于
![](/icons/51928yi.gif)
般应用来说
![](/icons/51928dou.gif)
这些功能有
![](/icons/51928yi.gif)
些华而不实
![](/icons/51928dou.gif)
其实能够实现目前类似于Google
![](/icons/51928de.gif)
查询语句分析功能其实对于大多数用户来说已经够了
![](/icons/51928dou2.gif)
所以
![](/icons/51928dou.gif)
Lucene早期版本
![](/icons/51928de.gif)
QueryParser仍是比较好
![](/icons/51928de.gif)
选择
![](/icons/51928dou2.gif)
添加修改删除指定记录(Document)
Lucene提供了索引
![](/icons/51928de.gif)
扩展机制
![](/icons/51928dou.gif)
因此索引
![](/icons/51928de.gif)
动态扩展应该是没有问题
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
而指定记录
![](/icons/51928de.gif)
修改也似乎只能通过记录
![](/icons/51928de.gif)
删除
![](/icons/51928dou.gif)
然后重新加入实现
![](/icons/51928dou2.gif)
如何删除指定
![](/icons/51928de.gif)
记录呢?删除
![](/icons/51928de.gif)
思路方法也很简单
![](/icons/51928dou.gif)
只是需要在索引时根据数据源中
![](/icons/51928de.gif)
记录ID专门另建索引
![](/icons/51928dou.gif)
然后利用IndexReader.delete(Termterm)思路方法通过这个记录ID删除相应
![](/icons/51928de.gif)
Document
![](/icons/51928dou2.gif)
根据某个字段值
![](/icons/51928de.gif)
排序功能
lucene缺省是按照自己
![](/icons/51928de.gif)
相关度算法(score)进行结果排序
![](/icons/51928de.gif)
![](/icons/51928dou.gif)
但能够根据其他字段进行结果排序是
![](/icons/51928yi.gif)
个在LUCENE
![](/icons/51928de.gif)
开发邮件列表中经常提到
![](/icons/51928de.gif)
问题
![](/icons/51928dou.gif)
很多原先基于数据库应用都需要除了基于匹配度(score)以外
![](/icons/51928de.gif)
排序功能
![](/icons/51928dou2.gif)
而从全文检索
![](/icons/51928de.gif)
原理我们可以了解到
![](/icons/51928dou.gif)
任何不基于索引
![](/icons/51928de.gif)
搜索过程效率都会导致效率非常
![](/icons/51928de.gif)
低
![](/icons/51928dou.gif)
如果基于其他字段
![](/icons/51928de.gif)
排序需要在搜索过程中访问存储字段
![](/icons/51928dou.gif)
速度回大大降低
![](/icons/51928dou.gif)
因此非常是不可取
![](/icons/51928de.gif)
![](/icons/51928dou2.gif)
但这里也有
![](/icons/51928yi.gif)
个折中
![](/icons/51928de.gif)
解决思路方法:在搜索过程中能够影响排序结果
![](/icons/51928de.gif)
只有索引中已经存储
![](/icons/51928de.gif)
docID和score这2个参数
![](/icons/51928dou.gif)
所以
![](/icons/51928dou.gif)
基于score以外
![](/icons/51928de.gif)
排序
![](/icons/51928dou.gif)
其实可以通过将数据源预先排好序
![](/icons/51928dou.gif)
然后根据docID进行排序来实现
![](/icons/51928dou2.gif)
这样就避免了在LUCENE搜索结果外对结果再次进行排序和在搜索过程中访问不在索引中
![](/icons/51928de.gif)
某个字段值
延伸阅读
最新评论