jun - 云代码空间
—— 相信 ,梦
Lucene 课程 第一天 核心语法
今天重点内容安排:
1、 索引在项目开发中使用
2、 什么是lucene ? lucene能够做什么 ?
3、 lucene快速入门
4、 分析索引内部结构原理
5、 核心API 详细分析
6、 基于lucene 结合 数据库实现 增删改查
7、 lucene 使用注意问题 (索引优化 … )
n 搜索引擎: 对互联网上资源, 建立索引 ,加速搜索
FTP资源、 网页资源 ---------- 音频、 视频、图片 建立索引
n Robot 网络机器人: 指在互联网上自动运行,指定特定任务一些程序
n Spider 网络爬虫 : 特殊网络机器人, 去互联网下载各种资源, 建立索引
爬虫 是所有搜索引擎 基础
用途一: 应用软件 (word 、 window操作系统、 myeclipse )
用途二: 贴吧、 论坛、 博客 (对于文章的搜索 ) ---- 最常见应用
用途三: 站内搜索 (京东 搜索商品、 51job 搜索招聘信息 ) --- 应用非常广
用途四: 专业搜索 (垂直领域搜索 818 工作网、 搜索引擎 baidu、google )
信息搜索的过程
第一步: 构建文本库 (对各种各样被搜索资源,提取文本信息 )
第二步: 对文本信息 建立索引
第三步: 结合索引 完成搜索
第四步: 对搜索结果排序显示
传统线性查找一个10MB的word文件,查找关键字如果在文档最后,大约3秒钟
倒排索引, 类似一本书的目录, 索引技术,是一项优化技术 ,提高查找速度
问题: 什么是lucene ?
Apache 提高 一套用于 进行全文信息检索java框架 (开源免费 )
Lucene 不是搜索引擎, 不可以直接当做软件或者产品使用 ,使用lucene 开发搜索引擎
问题: 什么是全文检索 ?
强调,对文本信息中每一个词,建立索引 ----- 全文检索(全文索引 )
Lucene 是全文索引 工具
官网:http://lucene.apache.org/ 下载开发jar包
企业使用lucene , 下载lucene (最新版本4.9 )、 下载 solr (是基于lucene搜索服务器 )
课程: lucene3.x
目录分析
n 开发lucene 导入 lucene-core-3.6.2.jar 核心jar包
n contrib 目录存放 lucene开发依赖工具jar包
开发项目 ,导入核心包 + contrib 依赖jar
导入jar 到工程
第一步: 提取文本数据 --- 转换 Document对象 (被存放在索引库中 )
第二步: 结合lucene API 对Document 建立索引
第三步: 结合luceneAPI 对索引库进行 查询
将对象数据 转换为Document (不管是什么数据,lucene只能操作Document)
需要使用Fieldable接口实现类 Field 构造
Field.Store 用来设置当前属性是否存放到索引库中 (搜索的结果)
Field.Index 用来设置当前属性是否索引库 建立索引 (搜索的过程)
n 设置索引目录Directory
n 设置分词器Analyzer
n 通过 IndexWriter 创建索引
查看索引内容工具 --- luke
可执行jar文件
通过 java –jar命令运行
问题: 为什么 id 、title、 content 都会被分词呢?
设置 Index.ANALYZED 对内容进行分词
如果设置 Index.NO 对属性,不会分词,建立词条 (用于搜索 )
文档视图
如果设置 Store.YES , 在文档数据中就会存在属性
如果设置Store.NO 属性就不会在Document中存储 (查询结果 )
n 搜索关键字 (用户输入)
n 设置索引目录Directory
n 设置分词器 Analyzer
n 搜索 获取Query 对象 (基于QueryParser分词搜索)
n 通过IndexSearcher对象,进行搜索
n 搜索结果按照得分排名 TopDocs
n 获取每个文档得分对象 ScoreDocs
Lucene 没有很好内置分词器, 企业使用lucene 采用企业级分词器 (免费、 收费)
索引库建立 都基于Document 和 Field API 存储数据
索引库建立 ,通过 IndexWriter API 完成
如果对搜索结果进行分词查找,使用QueryParser
MultiFieldQueryParser 支持搜索多个字段
索引库搜索, 基于Query抽象类对象完成, search包存放各种Query子类
和索引存储相关API ,在store包, FSDirectory 将索引保存在文件目录
在操作索引, 通常做法,将索引文件保存到硬盘 FSDirectory
如果对搜索操作进行优化, 使用RAMDirectory 与 FSDirectory 结合方式
分词器,在对文本建立全文索引时,对目标内容进行分词的
StandardAnalyzer 是lucene API内置 标准分词器, 对中文支持,每个字就是一个词
(企业级分词器 : IK分词器、 Paoding 分词器 … )
IK 分词器使用
下载 IKAnalyzer2012_u6.zip 最新版
使用IK分词器,在项目导入 IKAnalyzer.jar
核心配置文件 IKAnalyzer.cfg.xml (扩展词典、 停用词典)
n 扩展词典 ,对IK内置词典进行扩展
n 停用词典 ,有些词没有必要建立索引 啊、的、了、着 (不会出现在索引库)
默认停用词典stopword.dic
使用IK分词器建立索引
在实际应用中, 各种数据来源,提取出文本信息 --- 转换成Document对象
参考资源 : Lucene&Java精华版 第三章
name 属性: 属性名称 ,用于搜索、 用于获取结果
value 属性: 属性值, 被分词建立索引, 保存document中,作为查询结果
Store.YES 、StoreNO : document中是否存储这个属性,如果不存储,查询结果中没有该属性
Index.NO: 这个属性不建立索引
Index.ANALYZED:分词建立索引 (使用分词器)
Index.NOT_ANALYZED :不分词建立索引 (将属性value 完整作为一个词条 term)
(norm 作为分词参数, 影响得分,保存document中 ,如果内容分词越多, norm值越低 , 算分越低 )
Index.ANALYZED_NO_NORMS:分词索引, 在document中不保存 norm信息
Index.NOT_ANALYZED_NO_NORMS:不分词索引,在document中不保存 norm信息
NO_NORMS 存放方式 更加高效
案例: 如何选择Store和Index
思考: 要不要根据书号查询图书 ? (要不要对书号进行索引)
如果需要书号查询, 那么是否要求用户输入完整的书号 ? (如果索引,要不要分词 )
在查询结果中需不需要显示书号? (要不要将属性存储到Document )
可以设置IndexWriter的打开模式
OpenMode.APPEND 在原有索引库 ,增加索引 (默认)
OpenMode.CREATE 覆盖原来的索引库
CREATE 使用场景, FSDirectory 结合 RAMDirectory优化,使用
调用 IndexWriter的addDocument(Document) 添加新的索引
在IndexWriter操作索引库, 添加锁文件
当前其它线程,通过IndexWriter操作索引库,无法操作
org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@D:\work\sh_javaee20140513\lucene3_day1\index\write.lock
所以在实际开发中,如果多线程,同时操作索引库, 建立工具类, 提供唯一IndexWriter !
在程序运行时,多个线程获取到 同一个IndexWriter 对象
问题: 如何根据搜索内容建立 Query 对象
第一种: QueryParser 分词建立Query对象 ,根据输入内容进行分词,比较词条,只要有一个词条满足, 返回搜索结果
解析分词搜索 …. (QueryParser 只支持对一个字段搜索 !!!! )
指定多个字段搜索
第二种 : TermQuery 直接对词条搜索
直接搜索索引库词条 !!!
Term 作为完成词条搜索,不会被分词
IndexSearcher 和 IndexWriter 不同
IndexWriter 操作索引库 会加锁
IndexSearcher 不会加锁,多线程同时使用
IndexSearcher 对象不要定义static 全局变量, 因为每次返回 IndexSearcher 加载最新当前索引库, 如果返回同一个对象,造成索引库更新后,searcher内容没有更新 !
问题:
1、 一个软件 ,数据保存到数据库中, 索引库中存放什么?
2、 索引库和数据库 在软件中 是怎样的关系?
3、 软件项目中 为什么要使用索引技术 ?
4、 数据库中没有索引吗?
以论坛为例, 论坛需要发帖,帖子信息保存在数据库中 ,数据库可以对帖子列 进行索引 (数据库不支持全文索引 ) ----- 当执行帖子搜索 执行 content like ? , like 模糊查询无法使用数据库内部索引 , 导致大规模数据模糊搜索 性能非常差 ---------- lucene全文索引库解决这类问题 (建立词条,相同词合并 )
用户在开发中, 先查找索引库词条, 获取基本信息 (业务显示需要 ), 当点击详情查找数据库获取详细信息 (可以在索引库只存放数据记录id , 查找索引库,获取这些id ,再通过 id 查找数据库 )
保证索引库和数据库数据同步问题!!!
如何做到同步?? 在DAO 对数据进行增删改查同时,同时操作索引库
导入hibernate jar包, 导入配置文件 ,修改jdbc参数
JPA注解
Hbm映射
Service
DAO
操作数据库记录同时,操作索引库
建立索引
删除索引
修改索引
业务层 先查找索引库 获取记录id ,再查找数据库 获取记录
业务层代码 :
ArticleIndexDAO 先查找索引库,获取记录id
ArticleDAO 再根据id 查找数据库,获取Article对象
================ lucene 索引优化, 针对大数据 like 模糊搜索
如果mergeFactor 设置过大, 索引文件过多
如果 mergeFactor 设置过小, 单个索引文件 体积过大
默认操作索引库, 都是操作硬盘系统索引文件, 每次写入索引,在硬盘新建文件,每次读取索引,读取硬盘索引文件
在第一次操作索引库, 将硬盘中索引内容,都加载到内存中, 以后每次操作,都针对内容索引库进行, 在特定时间 (定时、 虚拟机退出), 将内存中索引库 回写到硬盘
问题: 如何将硬盘中索引文件读取到内存中 ?
问题 : 如何将内存中索引库,回写到硬盘上?
完整代码
在使用lucene索引库, 结合数据库方式
n 在增加、修改、删除 数据时 将数据库和索引库 进行同步
n 在like模糊搜索 时, 先查询索引库,获取记录id ,再查找数据库
什么是hibernate search ?
Hibernate Search是在apache Lucene的基础上建立的主要用于Hibernate的持久化模型的全文检索工具
下载 hibernate search
3.x 依赖hibernate3 ,lucene3.x
4.x 依赖hibernate4 ,lucene3.x
导入 hibernate-search-3.4.2.Final.jar (依赖hibernate和lucene )
第一步: 导入jar包,在hibernate 配置文件中 配置索引库位置
使用search后,索引由hibernate search 创建
第二步: 配置对哪些数据进行索引
@Indexd 对实体数据进行索引
@DocumentId 主键字段
@Field 属性进行索引,默认分词索引,不存储
@Analyzer 指定分词器
在hibernate 执行 增加、修改、删除, hibernate search 会自动 同步索引库 !
使用hibernate search 完成搜索
Hibernate search 封装,先查询索引库,获取id ,再查询数据库过程 !