Lucene全文检索
来源:互联网 发布:硕鼠for mac官网 编辑:程序博客网 时间:2024/06/05 17:40
搭建lucene的开发环境,要准备lucene的jar包,要加入的jar包至少有:
1) lucene-core-3.1.0.jar (核心包)
2) lucene-analyzers-3.1.0.jar (分词器)
3) lucene-highlighter-3.1.0.jar (高亮器)
4) lucene-memory-3.1.0.jar (高亮器)
今天学了Lucene的全文检索,写下一下笔记以供日后使用
1.1 全文检索的概念
1) 从大量的信息中快速、准确地查找出要的信息
2) 搜索的内容是文本信息(不是多媒体)
3) 搜索的方式:不是根据语句的意思进行处理。如果要搜索的文本为” 2012年的春晚有赵本山吗”,那么含有这些词(2012年、春晚、赵本山)就能搜索出来。每一个词都是关键词。
4) 全面、快速、准确是衡量全文检索系统的关键指标。
5) 概括:
a) 只处理文本
不处理语义
首先1:lucene全文检索是将客户端保存的对象转化成Document对象保存在制定的dir
所以写一个普通类转化成Document的对象是很重要的
将普通的Article对象转化成Document对象public static Document ArticleToDocument(Article article){ //创建Document对象<span style="font-family:Tahoma;"> </span>Document document = new Document();<span style="font-family:Tahoma;"> //因为只能保存String类型 的字符串,所以必须用lucene自带的类型转换器将int类型转化成String类型</span> String idStr = NumericUtils.longToPrefixCoded(article.getId()); <p> //Field<span style="font-family:宋体;">相当于</span><span style="font-family:Calibri;">JavaBean</span><span style="font-family:宋体;">的属性</span></p> //<p> /* a) 第一个参数为属性</p><p> b) 第二个参数为属性值</p><p align="left"> c) 第三个参数为是否往索引库里存储</p><p> d) 第四个参数为是否更新引索</p><p> 1) NO <span style="font-family:微软雅黑;">不进行引索</span></p><p> 2) ANALYZED <span style="font-family:微软雅黑;">进行分词引索</span></p><p> 3) NOT_ANALYZED <span style="font-family:微软雅黑;">进行引索,把整个输入作为一个词对待。*/</span></p> document.add(new Field("id", idStr, Store.YES, Index.NOT_ANALYZED));document.add(new Field("title", article.getTitle(), Store.YES, Index.ANALYZED));document.add(new Field("content", article.getContent(), Store.YES, Index.ANALYZED));return document;}//将Document对象转成Article对象public static Article DocumentToArticle(Document doc){Article article = new Article();<span style="font-family:Tahoma;"> //因为article是int类型所以也需要用自带的类型转换类转换成String类型</span> article.setId(NumericUtils.prefixCodedToLong(doc.get("id")));article.setTitle(doc.get("title"));article.setContent(doc.get("content"));return article;}
那么现在问题来了怎么将一个对象存储到本地硬盘上呢
好了,直接上代码
public void save(Article article){ IndexWriter indexWriter = null;try {// 配置当小文件的数量达到多少个后就自动合并为一个大文件,默认为10,最小为2.LuceneUtils.getIndexWriter().setMergeFactor(5); //<span style="font-family:Tahoma;">获得存储的位置 Directory directory = FSDirectory.open(new File("./directory")); //获得分词器</span><p> //IKAnalyzer.cfg.xml<span style="font-family:微软雅黑;">为</span><span style="font-family:Tahoma;">IKAnalyzer</span><span style="font-family:微软雅黑;">的配置文件,可以添加扩展词典和停止词典,一般放在classes根目录下</span></p> Analyzer=analyzer= new IKAnalyzer(); //获得indexWriter对象indexWriter = <span style="font-family:Tahoma;"></span>new IndexWriter(directory, analyzer, MaxFieldLength.LIMITED);// 把article转为documentDocument doc = ArticleDocumentUtils.ArticleToDocument(article);//将存储到索引中的doc对象得分乘以100(类似百度推广)//doc.setBoost(100);// 添加到索引中indexWriter.addDocument(doc);} catch (Exception e) {throw new RuntimeException(e);} <span style="font-family:Tahoma;">}</span>
1) 在数据库中,数据库中的数据文件存储在磁盘上。索引库也是同样,索引库中的索引数据也在磁盘上存在,我们用Directory这个类来描述。
2) 我们可以通过API来实现对索引库的增、删、改、查的操作。
3) 在数据库中,各种数据形式都可以概括为一种:表。在索引库中,各种数据形式也可以抽象出一种数据格式为Document。
4) Document的结构为:Document(List<Field>)
5) Field里存放一个键值对。键值对都为字符串的形式。
6) 对索引库中索引的操作实际上也就是对Document的操作。
我们发现上面的代码中的一些数据在删除修改查询的时候还要用到,所以我们要写一个工具类
public class LuceneUtils {private static Directory directory;private static Analyzer analyzer;private static IndexWriter indexWriter;static{try {directory = FSDirectory.open(new File("./directory"));analyzer= new IKAnalyzer();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
好了,存储完成了之后应该取出来了,那么怎么样获取存储的数据呢?还是直接上代码
public List<Article> search(String queryString,int first,int max) throws Exception{List<Article> list = new ArrayList<Article>();// 获得indexSearcher对象IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.getDirectory());// 将搜索条件转化为Query对象QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30,new String[] { "title", "content" }, LuceneUtils.getAnalyzer());Query query = queryParser.parse(queryString);//设置高亮//设置前缀和后缀Formatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");//scorer封装了关键字 Scorer 查询条件Scorer scorer= new QueryScorer(query);//Fragmenter设置文本的长度。默认为100。Fragmenter fragmenter = new SimpleFragmenter(15);//得到高亮器Highlighter highlighter = new Highlighter(formatter, scorer);//设置文本的长度,如果超过长度则显示不出来highlighter.setTextFragmenter(fragmenter);// 查到到前n条中间值TopDocs docs = indexSearcher.search(query,first+max);//总共查到的数据数量int count = docs.totalHits;ScoreDoc[] topDocs = docs.scoreDocs;//得到比较小的数字int min = Math.min(count,first+max);//分页处理for (int x = first; x <min; x++) {ScoreDoc sdoc = topDocs[x];int docId = sdoc.doc;Document document = indexSearcher.doc(docId);Article article = ArticleDocumentUtils.DocumentToArticle(document);/* * 使用高亮器 *//** * 1、分词器 * 查找关键词 * 2、字段 * 在哪个字段上进行高亮 * 3、字段的内容 * 把字段的内容提取出来 */String titleText = highlighter.getBestFragment(LuceneUtils.getAnalyzer(), "title", document.get("title"));String contentText = highlighter.getBestFragment(LuceneUtils.getAnalyzer(), "content", document.get("content"));if(titleText!=null){article.setTitle(titleText);}if(contentText!=null){article.setContent(contentText);}list.add(article);}return list;}查询肯定不止这一种啊,不然怎么查询所有的索引,所以介绍几种查询方法,由于查询是得到Query对象进行查询,所以不同的查询方法是得到不同的query对象
1、关键词查询
Term term = new Term("title","lucene");Query query = new TermQuery(term);
* 2、查询所有文档
Query query = new MatchAllDocsQuery();
* 3、范围查询
//查询id为5到15的所有对象Query query = NumericRangeQuery.newLongRange("id", 5L, 10L, true, true);//最后的两个布尔类型代表包涵不包含5和10
* 4、通配符查询
Term term = new Term("title","*.java");Query query = new WildcardQuery(term);
* 5、短语查询
因为不好用,不建议使用就不写了
* 6、Boolean查询
Term term = new Term("title","北京");TermQuery termQuery = new TermQuery(term);Term term2 = new Term("title","美女");TermQuery termQuery2 = new TermQuery(term2);Term term3 = new Term("title","北京美女");TermQuery termQuery3 = new TermQuery(term3);BooleanQuery query = new BooleanQuery();query.add(termQuery,Occur.SHOULD);query.add(termQuery2,Occur.SHOULD);query.add(termQuery3,Occur.SHOULD);
大概分页查找就这么多了,那么还有删除修改呢
public void delete(int id) {IndexWriter indexWriter = null;try {//indexWriter =LuceneUtils.getIndexWriter();// 从索引库中删除field为id的某一个值,<span style="font-family:Tahoma;">记得转换成String类型</span>indexWriter.deleteDocuments(new Term("id", NumericUtils.intToPrefixCoded(id)));} catch (Exception e) {throw new RuntimeException(e);} }
修改某一个id的article
public void modify(Article article) {IndexWriter indexWriter = null;try {//indexWriter =LuceneUtils.getIndexWriter();// 将article对象转化成document对象Document doc = ArticleDocumentUtils.ArticleToDocument(article);// 从索引库中删除field为id的某一个值indexWriter.deleteDocuments(new Term("id", NumericUtils.longToPrefixCoded(article.getId())));// 再添加到索引库中indexWriter.addDocument(doc);} catch (Exception e) {throw new RuntimeException(e);}}
到现在基本的lucene就差不多了,接着介绍一些细节
1,Directory
指向索引库的位置,有两种Directory
1FSDirectory
1) 通过FSDirectory.open(new File("./indexDir"))建立一个indexDir的文件夹,而这个文件夹就是索引库存放的位置。
2) 通过这种方法建立索引库时如果indexDire文件夹不存在,程序将自动创建一个,如果存在就用原来的这个。
3) 通过这个类可以知道所建立的索引库在磁盘上,能永久性的保存数据。这是优点
4) 缺点为因为程序要访问磁盘上的数据,这个操作可能引发大量的IO操作,会降低性能。
2RAMDirectory
1) 通过构造函数的形式Directory ramdirectory = new RAMDirectory(fsdirectory)可以建立RAMDirectory。
2) 这种方法建立的索引库会在内存中开辟一定的空间,通过构造函数的形式把fsdirectory移动到内存中。
3) 这种方法索引库中的数据是暂时的,只要内存的数据消失,这个索引库就跟着消失了。
因为程序是在内存中跟索引库交互,所以利用这种方法创建的索引的好处就在效率比较高,访问速度比较快。
2,MaxFieldLength
a) 能存储的最大长度
b) 在IndexWriter的构造方法里使用
c) 值为:
1) LIMITED 限制的最大长度 值为10000
2) UNLIMITED 没有限制的最大长度(一般不使用)
- Lucene 全文检索实践
- lucene 全文检索简介
- lucene 全文检索简介
- Lucene 全文检索
- 全文检索Lucene说明书
- 全文检索引擎lucene
- 全文检索LUCENE
- Lucene全文检索1
- lucene全文检索总结 .
- 全文检索--lucene
- lucene全文检索应用
- Lucene与全文检索
- lucene全文检索案例
- 初识全文检索Lucene
- 全文检索 Lucene
- 全文检索(lucene)
- lucene全文检索更新
- lucene 全文检索
- 实习小结——UIBarButtonItem和UINavigationBar的坑
- 运营开发规范化
- POJ1928 The Peanuts
- swappiness调整的调整
- HTML学习笔记(4)——CSS块级元素与盒模型
- Lucene全文检索
- Base64的简单使用
- HDFS的认识和理解
- linux下的文件权限
- 机房重构(二)--MDI窗体问题+优化的单例模式
- Keil MDK 点击增量编译 一直全部重新编译的解决办法
- Android之——常用手机号码功能
- android学习笔记(6)Activity高级+android:theme学习
- 无法安装Apple mobile device support 导致ipad(iphone)无法连接itunes的解决办法