Lucene介绍和使用方法

Lucene 是什么?一个开源的全文检索框架.

lucene流程:

Lucene的作用:

 

  1. 在对大量的数据进行检索的时候,lucene的检索速度比传统的SQL检索要快。
  2. 对查询的关键字进行处理。(更加清晰的展现在我们眼前)。

数据分类:结构化数据和非结构化数据。

  1. 结构化数据:指具有固定格式或有限长度的数据,如数据库中的数据,元数据等。
  2. 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件。


非结构化数据查询方法
顺序扫描法(Serial Scanning) 
        所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。
全文检索(Full-text Search) 
         将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。 
例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。 
这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。 
虽然创建索引的过程也是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以耗时间创建索引是值得的。

 使用案例:

package lucene_demo;

import java.nio.file.Paths;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
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.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
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.search.highlight.Formatter;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.Scorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.vectorhighlight.SimpleFieldFragList;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class LuceneDemo {

	public static void main(String[] args) {

		// addIndex();//添加索引

		 searchIndex();// 检索索引

		// updateIdnex();//更新索引

		// deleteIndex();//删除索引
	}

	/**
	 * 删除索引
	 */
	private static void deleteIndex() {
		try {
			// 指定索引目录
			Directory directory = FSDirectory.open(Paths.get("E:\\lucenedemo\\lucene_db\\studen_tb"));

			// 创建分词器(单字)
			Analyzer analyzer = new SmartChineseAnalyzer();

			IndexWriterConfig config = new IndexWriterConfig(analyzer);
			// 通过IndexWriterConfig指定索引的相关信息
			config.setOpenMode(OpenMode.CREATE_OR_APPEND);

			// 创建 更新 删除 都是IndexWriter来实现
			IndexWriter indexWriter = new IndexWriter(directory, config);

			// 删除索引
			indexWriter.deleteDocuments(new Term("studentID", "1"));

			// 提交事务
			indexWriter.commit();

			// 关闭流资源
			indexWriter.close();

			System.out.println("studnet luncene delete success !!!");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 更新索引
	 */
	private static void updateIdnex() {
		try {
			// 指定索引目录
			Directory directory = FSDirectory.open(Paths.get("E:\\lucenedemo\\lucene_db\\studen_tb"));

			// 创建智能分词器
			Analyzer analyzer = new SmartChineseAnalyzer();

			IndexWriterConfig config = new IndexWriterConfig(analyzer);
			// 通过IndexWriterConfig指定索引的相关信息
			config.setOpenMode(OpenMode.CREATE_OR_APPEND);

			// 创建 更新 删除 都是IndexWriter来实现
			IndexWriter indexWriter = new IndexWriter(directory, config);

			// 一个Document实例代表一条记录
			Document student = new Document();

			// StringField:不会对关键字进行分词
			student.add(new StringField("studentID", "1", Store.YES));
			student.add(new TextField("name", "李四", Store.YES));
			student.add(new TextField("scoreName", "Java", Store.YES));
			student.add(new TextField("score", "50", Store.YES));

			// 一个Document实例代表一条记录
			Document student2 = new Document();
			student2.add(new StringField("studentID", "2", Store.YES));
			student2.add(new TextField("name", "张三", Store.YES));
			student2.add(new TextField("scoreName", "Java", Store.YES));
			student2.add(new TextField("score", "60", Store.YES));

			// 通过IndexWriter 将数据更新至索引
			indexWriter.updateDocument(new Term("studentID", "1"), student);
			indexWriter.updateDocument(new Term("studentID", "2"), student2);
			// 提交事务
			indexWriter.commit();

			// 关闭流资源
			indexWriter.close();

			System.out.println("studnet luncene update success !!!");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void searchIndex() {
		try {
			// 指定索引目录
			Directory directory = FSDirectory.open(Paths.get("E:\\lucenedemo\\lucene_db\\studen_tb"));

			// 通过 DirectoryReader.open(directory) 读取的索引库信息,并返回相应的实例
			IndexReader indexReader = DirectoryReader.open(directory);

			// 通过 IndexSearcher 实例 来读取 数据
			IndexSearcher indexSearcher = new IndexSearcher(indexReader);

			//智能分词器
			Analyzer analyzer = new SmartChineseAnalyzer();
			
			//单条件查询
			//QueryParser queryParser = new QueryParser("title", analyzer);
			
			//MultiFieldQueryParser 多条件查询
			QueryParser QueryParser = new MultiFieldQueryParser(new String[] {"cityName"}, analyzer);
			
			
			//======================条件过滤=====================
			//查询的字段 广州或者襄阳  1.空格:广州 襄阳   2.or:广州 OR 襄阳
			Query query = QueryParser.parse("广州 OR 襄阳");
			
			//查询 广州和襄阳 1.AND:广州 AND 襄阳  2.+:+广州 +襄阳
			//Query query = QueryParser.parse("+广州 +襄阳");
			
			//查询标题中包含广州
			//Query query = QueryParser.parse("cityName:广州");
			
			//查询城市名称是广州,但是描述中没有广州的数据 1.AND NOT 2.-
			//Query query = QueryParser.parse("cityName:广州 AND NOT cityIntroduce:广州");
			
			//==================================================
			
			/********************高亮相关代码******************************/
			
			//格式器,通过格式器对关键字进行处理
			Formatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
			
			//通过Scorer 包装 Query
			Scorer fragmentScorer = new QueryScorer(query);
			
			//创建高亮器
			Highlighter highlighter = new Highlighter(formatter, fragmentScorer);
			
			//创建格式化片段
			Fragmenter fragmenter = new SimpleFragmenter(10);
			
			//讲格式化片段实例和高亮器进行关联  最终通过高亮器对文本信息处理
			highlighter.setTextFragmenter(fragmenter);
			
			/********************高亮相关代码******************************/
			
			// 读取数据
			TopDocs search = indexSearcher.search(query, 100);

			// 查询到的数据的数目
			ScoreDoc[] scoreDocs = search.scoreDocs;

			System.out.println("student message :" + scoreDocs.length);

			for (int i = 0; i < scoreDocs.length; i++) {
				// 从索引表中拿到关联数据表的
				int id = scoreDocs[i].doc;

				Document doc = indexSearcher.doc(id);

				/*String studentID = doc.get("studentID");
				String name = doc.get("name");
				String scoreName = doc.get("scoreName");
				String score = doc.get("score");

				System.out.println("学生ID:" + studentID + " 学生姓名:" + name + " 学科名称:" + scoreName + " 学科成绩:" + score);*/
				
				String cityID = doc.get("cityID");
				String cityName = doc.get("cityName");
				String cityIntroduce = doc.get("cityIntroduce");
				
				//System.out.println("cityID: "+ cityID+" cityName: "+ cityName + " cityIntroduce: "+cityIntroduce);
				
				//分词器 字段 文本信息
				String PsotcityName = highlighter.getBestFragment(analyzer, "cityName", cityName);
				String PostcityIntroduce = highlighter.getBestFragment(analyzer, "cityIntroduce", cityIntroduce);
				

				System.out.println("PsotcityName: "+ PsotcityName + "   --   PostcityIntroduce: "+PostcityIntroduce);
				
			}

			System.out.println("studnet luncene Search success !!!");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 添加索引
	 */
	private static void addIndex() {
		try {
			// 指定索引目录
			Directory directory = FSDirectory.open(Paths.get("E:\\lucenedemo\\lucene_db\\studen_tb"));

			// 创建智能分词器
			Analyzer analyzer = new SmartChineseAnalyzer();

			IndexWriterConfig config = new IndexWriterConfig(analyzer);
			// 通过IndexWriterConfig指定索引的相关信息
			config.setOpenMode(OpenMode.CREATE_OR_APPEND);

			// 创建 更新 删除 都是IndexWriter来实现
			IndexWriter indexWriter = new IndexWriter(directory, config);

			// 一个Document实例代表一条记录
			Document student = new Document();

			// StringField:不会对关键字进行分词
			student.add(new StringField("studentID", "1", Store.YES));
			student.add(new TextField("name", "李四", Store.YES));
			student.add(new TextField("scoreName", "Java", Store.YES));
			student.add(new TextField("score", "100", Store.YES));

			// 一个Document实例代表一条记录
			Document student2 = new Document();
			student2.add(new StringField("studentID", "2", Store.YES));
			student2.add(new TextField("name", "张三", Store.YES));
			student2.add(new TextField("scoreName", "Java", Store.YES));
			student2.add(new TextField("score", "90", Store.YES));

			// 一个Document实例代表一条记录
			Document city = new Document();
			city.add(new StringField("cityID", "1", Store.YES));
			city.add(new TextField("cityName", "广州", Store.YES));
			city.add(new TextField("cityIntroduce", "广州很好玩,有白云山著名旅游景点", Store.YES));
			
			// 一个Document实例代表一条记录
			Document city2 = new Document();
			city2.add(new StringField("cityID", "2", Store.YES));
			city2.add(new TextField("cityName", "襄阳", Store.YES));
			city2.add(new TextField("cityIntroduce", "襄阳有著名的广州投资企业", Store.YES));

			// 通过IndexWriter 将数据写入至索引库
			indexWriter.addDocument(student);
			indexWriter.addDocument(student2);
			indexWriter.addDocument(city);
			indexWriter.addDocument(city2);

			// 提交事务
			indexWriter.commit();

			// 关闭流资源
			indexWriter.close();

			System.out.println("studnet luncene create success !!!");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值