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

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

什么是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.关闭查询操作对象




运行结果:


下一步:

封装及优化,待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值