Lucene全文搜索学习笔记(一)

来源:互联网 发布:写日志的软件知乎 编辑:程序博客网 时间:2024/04/29 21:28

个人笔记之用,如有错误,恳请批评指正。

什么是lucene?

Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的架构,提供了完整的创建索引和查询索引,以及部分文本分析的引擎,Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎,Lucene在全文检索领域是一个经典的祖先,现在很多检索引擎都是在其基础上创建的,思想是相通的。

即:Lucene是根据关健字来搜索的文本搜索工具,只能在某个网站内部搜索文本内容,不能跨网站搜索。

 

Lucene通常用在什么地方?

Lucece不能用在互联网搜索(即像百度那样),只能用在网站内部的文本搜索(即只能在CRM,RAX,ERP内部使用),但思想是相通的。

 

为什么网站内部有些地方要用Lucene来索搜,而不全用SQL来搜索?

(1)SQL只能针对数据库表搜索,不能直接针对硬盘上的文本搜索

(2)SQL没有相关度排名

(3)SQL搜索结果没有关健字高亮显示

(4)SQL需要数据库的支持,数据库本身需要内存开销较大,例如:Oracle

(5)SQL搜索有时较慢,尤其是数据库不在本地时,超慢,例如:Oracle

 

使用Lucene的流程图?

创建索引库:

1)  创建JavaBean对象

2)  创建Docment对象

3)  将JavaBean对象所有的属性值,均放到Document对象中去,属性名可以和JavaBean相同或不同

4)  创建IndexWriter对象

5)  将Document对象通过IndexWriter对象写入索引库中

6)  关闭IndexWriter对象

根据关键字查询索引库中的内容:

1)  创建IndexSearcher对象

2)  创建QueryParser对象

3)  创建Query对象来封装关键字

4)  用IndexSearcher对象去索引库中查询符合条件的前100条记录,不足100条记录的以实际为准

5)  获取符合条件的编号

6)  用indexSearcher对象去索引库中查询编号对应的Document对象

7)  将Document对象中的所有属性取出,再封装回JavaBean对象中去,并加入到集合中保存,以备将之用。


Lucene快速入门

导入Lucene相关的jar包

  lucene-core-3.0.2.jar【Lucene核心】

  lucene-analyzers-3.0.2.jar【分词器】

  lucene-highlighter-3.0.2.jar【Lucene会将搜索出来的字,高亮显示,提示用户】

  lucene-memory-3.0.2.jar【索引库优化策略】

编写代码:

虚拟Article bean对象

package cn.ustb.lucene.entity;public class Article {private Integer id;private String  title;private String content;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public Article() {super();}public Article(Integer id, String title, String content) {super();this.id = id;this.title = title;this.content = content;}}
LuceneApp:

package cn.ustb.lucene.entity;import java.io.File;import java.util.ArrayList;import java.util.List;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.document.Field.Index;import org.apache.lucene.document.Field.Store;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriter.MaxFieldLength;import org.apache.lucene.queryParser.QueryParser;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.util.Version;import org.junit.Test;public class FirstLucene {public void createIndexDB(Article article){//documentDocument document = new Document();//创建lucene文档对象,并添加字段/*FIELD:: * Store.YES表示把当前字段存到文档中,Store.NO表示 不把当前字段存到文档中 * Index: * ANALYZED,表示当前字段建立索引,并且进行分词,产生多个term * NOT_ANALYZED,表示当前字段建立索引,但不进行分词,整个字段值作为一个整体,产生一个term * NO,不创建索引,以后不能用此字段查询 */document.add(new Field("id", article.getId().toString(), 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));Directory directory = null;Analyzer analyzer = null;IndexWriter indexWriter = null;try {//指定索引库目录directory = FSDirectory.open(new File("F:/java/practice/luceneDir"));//指定分词器 版本一般用最高版本analyzer = new StandardAnalyzer(Version.LUCENE_30);//创建索引库管理对象/**创建索引库管理对象(主要用来增删改索引库信息)* MaxFieldLength,用于限制Field的大小。这个变量可以让用户有计划地*对大文档Field进行截取。假如取值为10000,就只索引每个Field的前*10000个Term(关键字)。其它的部分都不会被Lucene索引,也不能被搜索到。*/indexWriter = new IndexWriter(directory, analyzer, MaxFieldLength.LIMITED);//添加文档对象到索引库管理对象indexWriter.addDocument(document);//提交到索引库indexWriter.commit();} catch (Exception e) {e.printStackTrace();}//关闭finally{if(indexWriter!=null){try {indexWriter.close();} catch (Exception e) {e.printStackTrace();}}}}public void findIndexDB(String keyWords){List<Article> articleList = new ArrayList<Article>();try {FSDirectory directory = FSDirectory.open(new File("F:/java/practice/luceneDir"));//分词器 :和存入时要一致Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);//索引库搜索者IndexSearcher indexSearcher = new IndexSearcher(directory);//指定查询解析器//参数一:版本号,一般选择最高,参数二:字段名,参数三:分词器QueryParser queryParser = new QueryParser(Version.LUCENE_30, "title", analyzer);//把查询关键字交给查询解析器,如果由多个单词组成,将匹配多个term 关键字,只要能匹配上任意一个单词都可以返回Query query = queryParser.parse(keyWords);//查询解析库//参数1:指定的查询解析器,参数二:指定返回记录条数TopDocs topDocs = indexSearcher.search(query, 5);System.out.println("实际索引库中匹配到的总条数为:"+topDocs.totalHits);System.out.println("返回的记录(ID)条数为:"+topDocs.scoreDocs.length);ScoreDoc[] scoreDocs = topDocs.scoreDocs;for (ScoreDoc scoreDoc : scoreDocs) {System.out.println("当前的文档积分是:"+scoreDoc.score);System.out.println("当前的文档编号是:"+scoreDoc.doc);//根据文档查看真正的文档对象Document document = indexSearcher.doc(scoreDoc.doc);System.out.println("真正文档的内容是:id:"+document.get("id")+";title:"+document.get("title")+";content:"+document.get("content"));}} catch (Exception e) {e.printStackTrace();}}@Testpublic void testIn(){Article article = new Article(1, "挖掘机修理哪家强?", "山东济南找蓝翔");createIndexDB(article);}@Testpublic void testOut(){String keyword = "挖掘机";findIndexDB(keyword);}}

新增操作说明

关键步骤与代码解说:

1.构建索引库

   Directory directory = FSDirectory.open(new File("索引库目录"));

2.指定分词器,版本一般指定为最高

         Analyzer analyzer = newStandardAnalyzer(Version.LUCENE_30);

3.创建文档对象,并添加相关字段值

         Document doc = new Document();

         doc.add(new Field("Id",goods.getGoodsId().toString(),Store.YES,Index.NOT_ANALYZED));

4.创建增删改索引库的操作对象,添加文档并提交

         IndexWriter indexWriter =new IndexWriter(directory,analyzer, MaxFieldLength.LIMITED);

         indexWriter.addDocument(doc);

         indexWriter.commit();

5.关闭操作对象

查询操作说明

关键步骤与代码解说:

1.打开索引库

directory= FSDirectory.open(new File("索引库目录"));

2。创建查询分词器,版本号与写入文档的查询分词器一样

         Analyzer analyzer = newStandardAnalyzer(Version.LUCENE_30);

3。创建查询解析器,参数为版本号,查询字段名,分词器

         QueryParser parser = new QueryParser(Version.LUCENE_30,"content",analyzer);

4。构建查询信息对象

         Query query = parser.parse(keyWord);

5。构建查询工具

         searcher = new IndexSearcher(directory);

6。通过查询工具执行查询。参数1,查询信息对象;参数2。返回记录数;TopDocs包括总记录数、文档重要信息(编号)的列表等

         TopDocs topDocx=searcher.search(query,20);

7。根据文档编号遍历真正的文档

         ScoreDoc sd[] = topDocx.scoreDocs;

         for(ScoreDoc scoreDoc:sd){

            。。。

            Document doc =searcher.doc(scoreDoc.doc);

8。转为java对象  setter(doc.get("param"));              

9.关闭查询操作对象




运行结果:


下一步:

封装及优化,待续...

0 0
原创粉丝点击