Lucene就是一个全文检索的工具,建立索引用的,类似于新华字典的目录

这里使用的是lucene-4.4.0版本,入门代码所需jar包如下图所示(解压lucene-4.4.0后的目录):

入门代码:

import java.io.File;
import java.io.IOException; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
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; /*8
* luceneDemo
*
*/
public class TestLucene {
/**
* 通过lucene 提供的api 对数据建立索引,indexWriter
* @throws IOException
*
*/
@Test
public void testAdd() throws IOException{ //索引在硬盘上面存放的位置..
Directory directory=FSDirectory.open(new File("D:/INDEX"));
//lucene 当前使用的版本...
Version matchVersion=Version.LUCENE_44;
//分词器...(把一段文本分词)(黑马程序员是高端的培训机构)
//analzyer 是一个抽象类,具体的切分词规则由子类实现...
Analyzer analyzer=new StandardAnalyzer(matchVersion); IndexWriterConfig config=new IndexWriterConfig(matchVersion, analyzer); //构造索引写入的对象..
IndexWriter indexWriter=new IndexWriter(directory, config); //往索引库里面写数据..
//索引库里面的数据都是document 一个document相当于是一条记录
//这个document里面的数据相当于索引结构..
Document document=new Document();
IndexableField indexableField=new IntField("id",1, Store.YES);
IndexableField stringfield=new StringField("title","对王召廷的个人评价",Store.YES);
IndexableField teIndexableField=new TextField("content","风流倜傥有点黄",Store.YES);
document.add(indexableField);
document.add(stringfield);
document.add(teIndexableField);
//索引库里面接收的数据都是document对象
indexWriter.addDocument(document);
indexWriter.close();
} /**
* 对建立的索引进行搜索...
* 通过indexSearcher 去搜索...
* @throws IOException
*/
@Test
public void testSearcher() throws IOException{ //索引在硬盘上面存放的位置..
Directory directory=FSDirectory.open(new File("D:/INDEX"));
//把索引目录里面的索引读取到IndexReader 当中...
IndexReader indexReader=DirectoryReader.open(directory);
// /构造搜索索引的对象..
IndexSearcher indexSearcher=new IndexSearcher(indexReader); //Query 它是一个查询条件对象,它是一个抽象类,不同的查询规则就构造不同的子类...
Query query=new TermQuery(new Term("title", "对王召廷的个人评价")); //检索符合query 条件的前面N 条记录..
//
TopDocs topDocs=indexSearcher.search(query, 10);
//返回总记录数...
System.out.println(topDocs.totalHits); //存放的都是document 的id
ScoreDoc scoreDocs []=topDocs.scoreDocs; for(ScoreDoc scoreDoc:scoreDocs){
//返回的就是document id
int docID=scoreDoc.doc;
//我还需要根据id 检索到对应的document
Document document=indexSearcher.doc(docID); System.out.println("id=="+document.get("id"));
System.out.println("title=="+document.get("title"));
System.out.println("content=="+document.get("content")); } } }

原理分析图:

demo演示: 

根据入门代码流程提炼工具类代码:

import java.io.File;
import java.io.IOException; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version; /**
* lucene 工具类...
* @author Administrator
*
*/
/**
* 提炼规则,假设这段代码可以完成一个功能,把这个代码提炼到一个方法里面去,假设这个方法在某个业务罗继承可以共用,那么往上抽取,
* 假设在其它逻辑层也可以用,提炼到工具类里面去。
*
*/
public class LuceneUtils {
private static IndexWriter indexWriter=null;
private static IndexSearcher indexSearcher=null; //索引存放目录..
private static Directory directory=null; private static IndexWriterConfig indexWriterConfig=null; private static Version version=null; private static Analyzer analyzer=null; static {
try {
directory=FSDirectory.open(new File(Constants.URL));
version=Version.LUCENE_44;
analyzer=new StandardAnalyzer(version);
indexWriterConfig=new IndexWriterConfig(version, analyzer);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* @return 返回用于操作索引的对象...
* @throws IOException
*/
public static IndexWriter getIndexWriter() throws IOException{
indexWriter=new IndexWriter(directory, indexWriterConfig);
return indexWriter;
}
/**
* 返回用于搜索索引的对象...
* @return
* @throws IOException
*/
public static IndexSearcher getIndexSearcher() throws IOException{ IndexReader indexReader=DirectoryReader.open(directory);
indexSearcher=new IndexSearcher(indexReader); return indexSearcher;
}
/**
*
* 返回lucene 当前的版本...
* @return
*/
public static Version getVersion() {
return version;
}
/**
*
* 返回lucene 当前使用的分词器..
* @return
*/
public static Analyzer getAnalyzer() {
return analyzer;
} }
public class Constants {
/**
* 索引存放的目录
*/
public static final String URL="d:/indexdir/news";
}

bean:

package cn.itcast.bean;

public class Article {
private int id; public int getId() {
return id;
} public void setId(int 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 String getAuthor() {
return author;
} public void setAuthor(String author) {
this.author = author;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} private String title; private String content; private String author; private String url; }

转换工具类:

package cn.itcast.lucene;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexableField; import cn.itcast.bean.Article; /*8
* 对象与索引库document 之间的转化
*
*/
public class ArticleToDocument { public static Document articleToDocument(Article article){
Document document=new Document();
IntField idfield=new IntField("id", article.getId(), Store.YES);
//StringField 对应的值不分词,textField 分词..
TextField titleField=new TextField("title", article.getTitle(),Store.YES);
TextField contentField=new TextField("content", article.getContent(),Store.YES);
//修改这个字段对应的权重值,默认这个值为1f
// contentField.setBoost(3f);
StringField authorField=new StringField("author", article.getAuthor(), Store.YES);
StringField urlField=new StringField("url", article.getUrl(), Store.YES);
document.add(idfield);
document.add(titleField);
document.add(contentField);
document.add(authorField);
document.add(urlField);
return document;
} }

Dao层:

package cn.itcast.dao;

import java.io.IOException;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.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 cn.itcast.bean.Article;
import cn.itcast.lucene.ArticleToDocument;
import cn.itcast.uitls.LuceneUtils; /**
* 使用lucene 的API 来操作索引库..
* @author Administrator
*
*/
public class LuceneDao { public void addIndex(Article article) throws IOException{
IndexWriter indexWriter=LuceneUtils.getIndexWriter();
Document doc=ArticleToDocument.articleToDocument(article);
indexWriter.addDocument(doc);
indexWriter.close();
} /**
* 删除符合条件的记录...
* @param fieldName
* @param fieldValue
* @throws IOException
*/
public void delIndex(String fieldName,String fieldValue) throws IOException{
IndexWriter indexWriter=LuceneUtils.getIndexWriter(); //一定要梦想,万一实现了勒
Term term=new Term(fieldName, fieldValue); indexWriter.deleteDocuments(term); indexWriter.close();
}
/**
*
* 更新
*
* update table set ? where condtion
* @throws IOException
*
*
*/
public void updateIndex(String fieldName,String fieldValue,Article article) throws IOException{
IndexWriter indexWriter=LuceneUtils.getIndexWriter();
/**
* 1:term 设置更新的条件...
*
* 2:设置更新的内容的对象..
*
*/
Term term=new Term(fieldName,fieldValue);
Document doc=ArticleToDocument.articleToDocument(article);
/**
*
* 在lucene 里面是先删除符合这个条件term 的记录,在创建一个doc 记录...
*
*/
indexWriter.updateDocument(term, doc);
indexWriter.close();
}
/**
* 0,10
* 10,10
* 20,10
* @param keywords
* @throws Exception
*/
public void findIndex(String keywords,int firstResult,int maxResult) throws Exception{ IndexSearcher indexSearcher=LuceneUtils.getIndexSearcher();
//第一个条件.. 单字段查询...
// Query query=new TermQuery(new Term("title","梦想")) //select * from table where fieldname="" or content="" String fields []={"title","content"}; //第二种条件:使用查询解析器,多字段。。。 我们需要重新导入一个jar queryParser 的jar... 位置在lucene解压后的queryparser文件夹下
QueryParser queryParser=new MultiFieldQueryParser(LuceneUtils.getVersion(),fields,LuceneUtils.getAnalyzer()); // /这个事一个条件..
Query query=queryParser.parse(keywords); //query 它是一个查询条件,query 是一个抽象类,不同的查询规则构造部同的子类即可
//检索符合query 条件的前面N 条记录...
//检索的是索引目录... (总记录数,socreDOC (docID))
//使用lucene 提供的api 进行操作...
TopDocs topDocs=indexSearcher.search(query,firstResult+maxResult);
// /存放的是docID
ScoreDoc scoreDocs []=topDocs.scoreDocs;
//判断:scoreDocs 的length (实际取出来的数量..) 与 firstResult+maxResult 的值取小值... //在java jdk 里面提供了一个api
int endResult=Math.min(scoreDocs.length, firstResult+maxResult); for(int i=firstResult;i<endResult;i++){
// /取出来的是docID,这个id 是lucene 自己来维护。
int docID=scoreDocs[i].doc;
Document document=indexSearcher.doc(docID);
System.out.println("id==="+document.get("id"));
System.out.println("title==="+document.get("title"));
System.out.println("content==="+document.get("content"));
System.out.println("url==="+document.get("url"));
System.out.println("author==="+document.get("author"));
} }
}

测试类:

package cn.itcast.junit;

import java.io.IOException;

import org.junit.Test;

import cn.itcast.bean.Article;
import cn.itcast.dao.LuceneDao; /**
* 测试luceneDao
* @author Administrator
*
*/
public class LuceneDaoTest { private LuceneDao luceneDao=new LuceneDao(); @Test
public void testCreate() throws IOException{
for(int i=28;i<=28;i++){
Article article=new Article();
article.setId(i);
article.setTitle("一定要梦想,万一实现了勒");
article.setContent("矫情我觉得这句话太矫情了矫情矫情矫情矫情矫情矫情");
article.setUrl("http://www.tianmao.com");
article.setAuthor("马云");
luceneDao.addIndex(article);
} }
@Test
public void testsearcher() throws Exception{
// article.setTitle("一定要梦想,万一实现了勒"); textfield 分词 标准分词器
// article.setContent("我觉得这句话太矫情了"); textfield 分词 标准分词器
luceneDao.findIndex("梦想",20,10); }
@Test
public void testdelete() throws IOException{
String fieldName="title";
String fieldValue="定";
luceneDao.delIndex(fieldName, fieldValue);
} @Test
public void testUpdate() throws IOException{
String fieldName="title";
String fieldValue="定"; Article article=new Article();
article.setId(9527);
article.setTitle("一定要梦想,万一实现了勒");
article.setContent("我觉得这句话太矫情了");
article.setUrl("http://www.tianmao.com");
article.setAuthor("马云"); luceneDao.updateIndex(fieldName, fieldValue, article); } }

分词器的流程图:

关于分词器,网上可以找到很多种类的分词器配合Lucene使用,相关分词规则查看对应说明。

举例如下:

Analyzer analyzer=new StandardAnalyzer(Version.LUCENE_44);//中文单字切分、英文按空格切分成单词

Analyzer analyzer=new CJKAnalyzer(Version.LUCENE_44);//二分法分词,中文相连的两个词作为一个索引

Analyzer analyzer=new IKAnalyzer();//第三方的分词器,对中文支持较好,可以自定义分词单词与停用词

索引库优化

package cn.itcast.lucene;

import java.io.File;
import java.io.IOException; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LogDocMergePolicy;
import org.apache.lucene.index.MergePolicy;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test; import cn.itcast.uitls.Constants; public class TestOptimise {
/*8
* 优化的第一种方式:通过 IndexWriterConfig 优化设置mergePolicy(合并策略)
*
*
*/
public void testoptimise() throws IOException{
Directory directory=FSDirectory.open(new File(Constants.URL)); Analyzer analyzer=new StandardAnalyzer(Version.LUCENE_44);
IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_44, analyzer); LogDocMergePolicy mergePolicy=new LogDocMergePolicy(); /**
* 当这个值越小,更少的内存会被运用当创建索引的时候,搜索的时候越快,创建的时候越慢。
* 当这个值越大,更多的内存会被运用当创建索引的时候,搜索的时候越慢,创建的时候越快..
* larger values >10
*
* 2<=smaller<=10
*
*/
//设置合并因子..
mergePolicy.setMergeFactor(10);
// /设置索引的合并策略..
config.setMergePolicy(mergePolicy);
IndexWriter indexWriter=new IndexWriter(directory, config);
} /**
* 通过directory 去优化....
* @throws IOException
*
*/
@Test
public void testoptimise2() throws IOException{
//现在的索引放在硬盘上面...
Directory directory=FSDirectory.open(new File(Constants.URL));
// /通过这个对象吧directory 里面的数据读取到directory1 里面来..
IOContext ioContext=new IOContext();
//相办法吧directory 的索引读取到内存当中来...
Directory directory1=new RAMDirectory(directory,ioContext);
IndexReader indexReader=DirectoryReader.open(directory1);
IndexSearcher indexSearcher=new IndexSearcher(indexReader);
Query query=new TermQuery(new Term("title", "想"));
TopDocs topDocs=indexSearcher.search(query, 100);
System.out.println(topDocs.totalHits);
} /**
* 索引文件越大,会影响检索的速度.. (减少索引文件的大小)
*
* 1:排除停用词..
*
*/
public void testoptimise3(){ }
/**
* 将索引分目盘存放 将数据归类...
*
*/
public void testoptimise4(){ }
}

最新文章

  1. spring数据源配置
  2. 23Mybatis_根据订单商品数据模型的练习对resultMap和resulttype的总结
  3. 复制本贴地址传给QQ/MSN好友的代码
  4. PowerShell 4 on win7 sp1
  5. 从报错“无效操作,连接被关闭”探究Transaction的Timeout超时机制
  6. 十款基础级WordPress插件
  7. Codeforces Gym 100637G G. #TheDress 暴力
  8. Effective C# Chapter1-Language Elements
  9. Ext.net中常用的三种交互方式
  10. 关于JS中变量提升的规则和原理的一点理解
  11. AEAI WM v1.6.0 升级说明,开源工作管理系统
  12. LATeX 插入脚注
  13. Python2.7设置在shell脚本中自动补全功能的方法
  14. MVC使用StructureMap实现依赖注入Dependency Injection
  15. cocos2dx常见Action(转)
  16. SpringBoot管理Banner
  17. removeFromParentAndCleanup和callfuncN_selector
  18. JSON 解析出错问题
  19. [精校版]The Swift Programming Language--语言指南--字符串和字符 (转)
  20. soapUI的简单使用(webservice接口功能测试)

热门文章

  1. Lingo解决最优化问题
  2. Luogu P1802 5倍经验日_KEY
  3. 北京Uber优步司机奖励政策(1月28日)
  4. Python-特殊变量
  5. 使用Google Cloud Messaging (GCM),PHP 开发Android Push Notifications (安卓推送通知)
  6. Ruby 基础教程1-6
  7. Ruby 基础教程1-4
  8. 【独家】K8S漏洞报告 | 近期bug fix解读&amp;1.9.11主要bug fix汇总
  9. 「日常训练」ZgukistringZ(Codeforces Round #307 Div. 2 B)
  10. 第三模块:面向对象&amp;网络编程基础 第3章 选课系统作业讲解