Lucene索引并检索数据库

1.Lucene简介

Lucene是一个开源的全文检索引擎工具包,它提供了完整的索引引擎、查询引擎和部分文本分析引擎。Lucene为软件开发人员提供了一套简单易用的检索引擎开发工具包,以便在系统中实现全文检索功能,或者以Lucene为基础建立一套完整的全文检索引擎。

全文搜索引擎的工作原理:扫描问答库中的每一条记录并分词建立索引,索引记录了词在每一条问答记录中出现的次数和位置,当收到用户的问题时,也会对问题进行分词,然后从索引中找出包含这些词的所有回答记录,再分别计算这些问答记录与用户问题的相似度,找出相似度最高的一条回答记录返回给用户。

Lucene的优点:索引文件格式独立于应用平台、高效的索引引擎、强大的查询引擎、易扩展。

2.Lucene索引和检索原理

Lucene能够对任何数据做索引和检索,像txt、word、pdf、数据库等格式的数据源,我们都可以通过其他工具或编程方式将这些格式的数据读取出来,转化为文本形式的数据,这样就能使用Lucene对这些文本数据建立索引以及做检索。

3.Lucene索引和检索数据库

1.创建JDBC获取Connection工具类

package com.tgb.org;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * JDBC获取Connection工具类
 * @author quwenzhe
 *
 */
public class JdbcUtil {
	private static Connection conn = null;
	private static final String URL = "jdbc:mysql://localhost:3306/lucene";
	private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
	private static final String USER_NAME = "root";
	private static final String PASSWORD = "root";

	public static Connection getConnection() {
		try {
			Class.forName(JDBC_DRIVER);
			conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
}

2.创建JavaBean类

package com.tgb.org;

public class UserInfo {
	private String id;
	private String username;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}
}

3.对数据库信息创建索引并对索引进行检索

package com.tgb.org;

import java.io.File;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
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 org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;

public class SearchLogic {
	private static Connection conn = null;
	private static Statement stmt = null;
	private static ResultSet rs = null;
	// 索引保存目录
	private String indexDir = "D:\\lucence\\index2";
	private static IndexSearcher searcher = null;
	//创建分词器
	private static Analyzer analyzer = new IKAnalyzer(true);

	/**
	 * 获取数据库数据
	 * @param queryStr 需要检索的关键字
	 * @return
	 * @throws Exception
	 */
	public List<UserInfo> getResult(String queryStr) throws Exception {
		List<UserInfo> result = null;
		conn = JdbcUtil.getConnection();
		if (conn == null) {
			throw new Exception("数据库连接失败!");
		}
		String sql = "select id, username from t_user";
		try {
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);
			// 给数据库创建索引,此处执行一次,不要每次运行都创建索引
			// 以后数据有更新可以后台调用更新索引
			this.createIndex(rs);
			TopDocs topDocs = this.search(queryStr);
			ScoreDoc[] scoreDocs = topDocs.scoreDocs;
			result = this.addHits2List(scoreDocs);
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("数据库查询sql出错! sql : " + sql);
		} finally {
			if (rs != null)
				rs.close();
			if (stmt != null)
				stmt.close();
			if (conn != null)
				conn.close();
		}
		return result;
	}

	/**
	 * 为数据库检索数据创建索引
	 * @param 访问数据库返回的ResultSet
	 * @throws Exception
	 */
	private void createIndex(ResultSet rs) throws Exception {
		// 创建或打开索引
		Directory directory = FSDirectory.open(new File(indexDir));
		// 创建IndexWriter
		IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_46,
				analyzer);
		IndexWriter indexWriter = new IndexWriter(directory, conf);
		// 遍历ResultSet创建索引
		while (rs.next()) {
			// 创建document并添加field
			Document doc = new Document();
			doc.add(new TextField("id", rs.getString("id"), Field.Store.YES));
			doc.add(new TextField("username", rs.getString("username"),
					Field.Store.YES));
			// 将doc添加到索引中
			indexWriter.addDocument(doc);
		}
		indexWriter.commit();
		indexWriter.close();
		directory.close();
	}

	/**
	 * 检索索引
	 * @param queryStr 需要检索的关键字
	 * @return
	 * @throws Exception
	 */
	private TopDocs search(String queryStr) throws Exception {
		//创建或打开索引目录
		Directory directory = FSDirectory.open(new File(indexDir));
		IndexReader reader = IndexReader.open(directory);
		if (searcher == null) {
			searcher = new IndexSearcher(reader);
		}
		//使用查询解析器创建Query
		QueryParser parser = new QueryParser(Version.LUCENE_46, "username",
				analyzer);
		Query query = parser.parse(queryStr);
		//从索引中搜索得到排名前10的文档
		TopDocs topDocs = searcher.search(query, 10);
		return topDocs;
	}

	/**
	 * 将检索结果添加到List中
	 * @param scoreDocs
	 * @return
	 * @throws Exception
	 */
	private List<UserInfo> addHits2List(ScoreDoc[] scoreDocs) throws Exception {
		List<UserInfo> listBean = new ArrayList<UserInfo>();
		UserInfo bean = null;
		for (int i = 0; i < scoreDocs.length; i++) {
			int docId = scoreDocs[i].doc;
			Document doc = searcher.doc(docId);
			bean = new UserInfo();
			bean.setId(doc.get("id"));
			bean.setUsername(doc.get("username"));
			listBean.add(bean);
		}
		return listBean;
	}

	public static void main(String[] args) {
		SearchLogic logic = new SearchLogic();
		try {
			Long startTime = System.currentTimeMillis();
			List<UserInfo> result = logic.getResult("屈文哲");
			int i = 0;
			for (UserInfo bean : result) {
				if (i == 10)
					break;
				System.out.println("bean.name " + bean.getClass().getName()
						+ " : bean.id " + bean.getId() + " : bean.username "
						+ bean.getUsername());
				i++;
			}

			System.out.println("searchBean.result.size : " + result.size());
			Long endTime = System.currentTimeMillis();
			System.out.println("查询所花费的时间为:" + (endTime - startTime) / 1000);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(e.getMessage());
		}
	}
}

项目依赖的jar:

看完上述代码我们可以发现,Lucene对访问数据库的返回值ResultSet建立索引,然后通过对索引进行检索,检索出符合条件的数据,从而提高对数据库的查询效率。

时间: 2024-10-12 16:56:44

Lucene索引并检索数据库的相关文章

使用Lucene索引和检索POI数据

使用Lucene索引和检索POI数据 摘要: 1.简介 关于空间数据搜索,以前写过<使用Solr进行空间搜索>这篇文章,是基于Solr的GIS数据的索引和检索. Solr和ElasticSearch这两者都是基于Lucene实现的,两者都可以进行空间搜索(Spatial Search),在有些场景,我们需要把Lucene嵌入到已有的系统提供... 1.简介 关于空间数据搜索,以前写过<使用Solr进行空间搜索>这篇文章,是基于Solr的GIS数据的索引和检索. Solr和Elast

用Lucene检索数据库

http://blog.sina.com.cn/s/blog_82ac67c101012r9z.html package com.javabean; import java.io.File;import java.io.IOException;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List; import org.apache.lucen

基于lucene的案例开发:实时索引的检索

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44279753 http://www.llwjy.com/blogdetail/31bb705106379feaf6d31b58dd777be6.html 个人博客小站搭建成功,网址 www.llwjy.com,欢迎大家来吐槽~ 在前面的博客中,我们已经介绍了IndexSearcher中的检索方法,也介绍了如何基于lucene中的NRT*类去创建实时索引,在这篇博客中我们就重点介

MySQL和Lucene索引对比分析

MySQL和Lucene都可以对数据构建索引并通过索引查询数据,一个是关系型数据库,一个是构建搜索引擎(Solr.ElasticSearch)的核心类库.两者的索引(index)有什么区别呢?以前写过一篇<Solr与MySQL查询性能对比>,只是简单的对比了下查询性能,对于内部原理却没有解释,本文简单分析下两者的索引区别. MySQL索引实现 在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式. M

lucene 索引合并策略

在索引算法确定的情况下,最为影响Lucene索引速度有三个参数--IndexWriter中的 MergeFactor, MaxMergeDocs, RAMBufferSizeMB .这些参数无非是控制内外存交换和索引合并频率,从而达到提高索引速度.当然这些参数的设置也得依照硬件条件灵活设置. MaxMergeDocs该参数决定写入内存索引文档个数,到达该数目后就把该内存索引写入硬盘,生成一个新的索引segment文件. 所以该参数也就是一个内存buffer,一般来说越大索引速度越快. MaxBu

Luke 5—— 可视化 Lucene 索引查看工具,可以查看ES的索引

Luke 5 发布,可视化 Lucene 索引查看工具  oschina 发布于2015年08月31日 这是一个主要版本,该版本支持 Lucene 5.2.0. 它支持 elasticsearch 1.6.0(Lucene的4.10.4) 已解决的问题:#20增加支持重建索引并不会存储领域,不暴露位置的字段值. Pull Requests:#23 Elasticsearch 支持和阴影插件组装#26 添加 .gitignore 文件#27 支持 Lucene 5#28 luke.sh 新增LUK

一步一步跟我学习lucene(18)---lucene索引时join和查询时join使用示例

了解sql的朋友都知道,我们在查询的时候可以采用join查询,即对有一定关联关系的对象进行联合查询来对多维的数据进行整理.这个联合查询的方式挺方便的,跟我们现实生活中的托人找关系类似,我们想要完成一件事,先找自己的熟人,然后通过熟人在一次找到其他,最终通过这种手段找到想要联系到的人.有点类似于"世间万物皆有联系"的感觉. lucene的join包提供了索引时join和查询时join的功能: Index-time join 大意是索引时join提供了查询时join的支持,且IndexWr

lucene索引库的增删改查操作

1. 索引库的操作 保持数据库与索引库的同步 说明:在一个系统中,如果索引功能存在,那么数据库和索引库应该是同时存在的.这个时候需要保证索引库的数据和数据库中的数据保持一致性.可以在对数据库进行增.删.改操作的同时对索引库也进行相应的操作.这样就可以保证数据库与索引库的一致性. 工具类DocumentUtils 在对索引库进行操作时,增.删.改过程要把一个JavaBean封装成Document,而查询的过程是要把一个Document转化成JavaBean.在进行维护的工作中,要反复进行这样的操作

搜索引擎系列五:Lucene索引详解(IndexWriter详解、Document详解、索引更新)

一.IndexWriter详解 问题1:索引创建过程完成什么事? 分词.存储到反向索引中 1. 回顾Lucene架构图: 介绍我们编写的应用程序要完成数据的收集,再将数据以document的形式用lucene的索引API创建索引.存储. 这里重点要强调应用代码负责做什么,lucene负责做什么. 2. Lucene索引创建API 图示 通过该图介绍lucene创建索引的核心API:Document.IndexWriter Lucene中要索引的文档.数据记录以document表示,应用程序通过I