个人笔记之用,如有错误,恳请批评指正。
什么是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){
//document
Document 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();
}
}
@Test
public void testIn(){
Article article = new Article(1, "挖掘机修理哪家强?", "山东济南找蓝翔");
createIndexDB(article);
}
@Test
public 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.关闭查询操作对象
下一步:
封装及优化,待续...