lucene 搜索mysql数据库_Lucene检索数据库(入门篇),支持中文检索

全文分两部分:

一:Lucene简介

Lucene版本:3.0.2

全文检索大体分两个部分:索引创建(Indexing)和搜索索引(Search)

1. 索引过程:

1) 有一系列被索引文件(此处所指即数据库数据)

2) 被索引文件经过语法分析和语言处理形成一系列词(Term)。

3) 经过索引创建形成词典和反向索引表。

4) 通过索引存储将索引写入硬盘。

2. 搜索过程:

a) 用户输入查询语句。

b) 对查询语句经过语法分析和语言分析得到一系列词(Term)。

c) 通过语法分析得到一个查询树。

d) 通过索引存储将索引读入到内存。

e) 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档。

f) 将搜索到的结果文档对查询的相关性进行排序。

g) 返回查询结果给用户。

· 索引过程如下:

创建一个IndexWriter用来写索引文件,它有几个参数,INDEX_DIR就是索引文件所存放的位置,Analyzer便是用来对文档进行词法分析和语言处理的。

创建一个Document代表我们要索引的文档。

将不同的Field加入到文档中。我们知道,一篇文档有多种信息,如题目,作者,修改时间,内容等。不同类型的信息用不同的Field来表示,在本例子中,一共有两类信息进行了索引,一个是文件路径,一个是文件内容。其中FileReader的SRC_FILE就表示要索引的源文件。

IndexWriter调用函数addDocument将索引写到索引文件夹中。

· 搜索过程如下:

IndexReader将磁盘上的索引信息读入到内存,INDEX_DIR就是索引文件存放的位置。

创建IndexSearcher准备进行搜索。

创建Analyer用来对查询语句进行词法分析和语言处理。

创建QueryParser用来对查询语句进行语法分析。

QueryParser调用parser进行语法分析,形成查询语法树,放到Query中。

IndexSearcher调用search对查询语法树Query进行搜索,得到结果TopScoreDocCollector。

二:代码示例(本文重点部分)

1) 首先是连接数据库的jdbc配置文件信息以及存放索引文件的路径配置信息

Test.properties代码  58063579_1.pngjdbc.driverClassName = com.mysql.jdbc.Driver

jdbc.url = jdbc:mysql://192.168.0.1/dbname?autoReconnect=true&characterEncoding=utf8

jdbc.username = root

jdbc.password = password

jdbc.maxIdle = 2

jdbc.maxActive = 4

jdbc.maxWait = 5000

jdbc.validationQuery = select 0

res.index.indexPath = D\:\\apache-tomcat-6.0.18\\webapps\\test\\testHome\\search\\res\\index1

res.index.mainDirectory = D\:\\apache-tomcat-6.0.18\\webapps\\test\\testHome\\search\\res

2) 读取资源文件的工具类:

Java代码  58063579_1.pngpackage com.test.common;

import java.io.IOException;

import java.io.InputStream;

import java.util.HashMap;

import java.util.Map;

import java.util.Properties;

/**

* PropertiesUtil.java

* @version 1.0

* @createTime 读取配置文件信息类

*/

public class PropertiesUtil {

private static String defaultPropertyFilePath = "/test.properties";

private static Map ppsMap = new HashMap();

/**

* 读取默认文件的配置信息,读key返回value

* @param key

* @return value

*/

public static final String getPropertyValue(String key) {

Properties pps = getPropertyFile(defaultPropertyFilePath);

return pps == null  null : pps.getProperty(key);

}

/**

* 传入filePath读取指定property文件,读key返回value

* @param propertyFilePath

* @param key

* @return value

*/

public static String getPropertyValue(String propertyFilePath,String key) {

if(propertyFilePath == null) {

propertyFilePath = defaultPropertyFilePath;

}

Properties pps = getPropertyFile(propertyFilePath);

return pps == null  null : pps.getProperty(key);

}

/**

* 根据path返回property文件,并保存到HashMap中,提高效率

* @param propertyFilePath

* @return

*/

public static Properties getPropertyFile(String propertyFilePath) {

if(propertyFilePath == null) {

return null;

}

Properties pps = ppsMap.get(propertyFilePath);

if(pps == null) {

InputStream in = PropertiesUtil.class.getResourceAsStream(propertyFilePath);

pps = new Properties();

try {

pps.load(in);

} catch (IOException e) {

e.printStackTrace();

}

ppsMap.put(propertyFilePath, pps);

}

return pps;

}

}

3) Jdbc连接数据库获取Connection工具类,不做分析,直接上代码

Java代码  58063579_1.pngpackage com.test.common;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

/**

* JdbcUtil.java

* @version 1.0

* @createTime JDBC获取Connection工具类

*/

public class JdbcUtil {

private static Connection conn = null;

private static final String URL;

private static final String JDBC_DRIVER;

private static final String USER_NAME;

private static final String PASSWORD;

static {

URL = PropertiesUtil.getPropertyValue("jdbc.url");

JDBC_DRIVER = PropertiesUtil.getPropertyValue("jdbc.driverClassName");

USER_NAME = PropertiesUtil.getPropertyValue("jdbc.username");

PASSWORD = PropertiesUtil.getPropertyValue("jdbc.password");

}

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;

}

}

4) 万事具备,只欠东风了,下面是核心部分,方法都有注释,不多说了,一步步来,我想肯定是没有问题的。代码如下:

Java代码  58063579_1.pngpackage com.test.lucene.logic;

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.Field.TermVector;

import org.apache.lucene.index.IndexWriter;

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.Searcher;

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;

import org.wltea.analyzer.lucene.IKSimilarity;

import com.test.common.JdbcUtil;

import com.test.common.PropertiesUtil;

import com.test.lucene.model.SearchBean;

/**

* SearchLogic.java

* @version 1.0

* @createTime Lucene数据库检索

*/

public class SearchLogic {

private static Connection conn = null;

private static Statement stmt = null;

private static  ResultSet rs = null;

private String searchDir = PropertiesUtil.getPropertyValue("res.index.indexPath");

private static File indexFile = null;

private static Searcher searcher = null;

private static Analyzer analyzer = null;

/** 索引页面缓冲 */

private int maxBufferedDocs = 500;

/**

* 获取数据库数据

* @return ResultSet

* @throws Exception

*/

public List getResult(String queryStr) throws Exception {

List result = null;

conn = JdbcUtil.getConnection();

if(conn == null) {

throw new Exception("数据库连接失败!");

}

String sql = "select articleid,title_en,title_cn,abstract_en,abstract_cn from p2p_jour_article";

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 rs

* @throws Exception

*/

private void createIndex(ResultSet rs) throws Exception {

Directory directory = null;

IndexWriter indexWriter = null;

try {

indexFile = new File(searchDir);

if(!indexFile.exists()) {

indexFile.mkdir();

}

directory = FSDirectory.open(indexFile);

analyzer = new IKAnalyzer();

indexWriter = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);

indexWriter.setMaxBufferedDocs(maxBufferedDocs);

Document doc = null;

while(rs.next()) {

doc = new Document();

Field articleid = new Field("articleid", String.valueOf(rs

.getInt("articleid")), Field.Store.YES,

Field.Index.NOT_ANALYZED, TermVector.NO);

Field abstract_cn = new Field("abstract_cn", rs

.getString("abstract_cn") == null  "" : rs

.getString("abstract_cn"), Field.Store.YES,

Field.Index.ANALYZED, TermVector.NO);

doc.add(articleid);

doc.add(abstract_cn);

indexWriter.addDocument(doc);

}

indexWriter.optimize();

indexWriter.close();

} catch(Exception e) {

e.printStackTrace();

}

}

/**

* 搜索索引

* @param queryStr

* @return

* @throws Exception

*/

private TopDocs search(String queryStr) throws Exception {

if(searcher == null) {

indexFile = new File(searchDir);

searcher = new IndexSearcher(FSDirectory.open(indexFile));

}

searcher.setSimilarity(new IKSimilarity());

QueryParser parser = new QueryParser(Version.LUCENE_30,"abstract_cn",new IKAnalyzer());

Query query = parser.parse(queryStr);

TopDocs topDocs = searcher.search(query, searcher.maxDoc());

return topDocs;

}

/**

* 返回结果并添加到List中

* @param scoreDocs

* @return

* @throws Exception

*/

private List addHits2List(ScoreDoc[] scoreDocs ) throws Exception {

List listBean = new ArrayList();

SearchBean bean = null;

for(int i=0 ; i

int docId = scoreDocs[i].doc;

Document doc = searcher.doc(docId);

bean = new SearchBean();

bean.setArticleid(doc.get("articleid"));

bean.setAbstract_cn(doc.get("abstract_cn"));

listBean.add(bean);

}

return listBean;

}

public static void main(String[] args) {

SearchLogic logic = new SearchLogic();

try {

Long startTime = System.currentTimeMillis();

List result = logic.getResult("急性   肺   潮气量   临床试验");

int i = 0;

for(SearchBean bean : result) {

if(i == 10) break;

System.out.println("bean.name " + bean.getClass().getName()

+ " : bean.articleid " + bean.getArticleid()

+ " : bean.abstract_cn " + bean.getAbstract_cn());

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());

}

}

}

5) 第四步用到了一个SearchBean,其实这就是一个javabean文件,包含两个String类型(articleid和abstract_cn)的set、get方法,自己回去补上吧。

顺便说下数据库表结构:

tablename随便取,但要跟上面查询中的表对应

表字段:articleid  int 类型

abstract_cn   varchar类型

对表字段没有太严格的定义,本来就是用来测试的。

6) 最后给大家提供所使用到的jar包列表:

IKAnalyzer3.2.5Stable.jar(一位好心人建议我升级一下jar包,呵呵,最新的jar包名为:IKAnalyzer3.2.8.jar ,谢谢了!)

lucene-analyzers-3.0.2

lucene-core-3.0.2

lucene-highlighter-3.0.2

lucene-memory-3.0.2

lucene-queries-3.0.2

mysql-connector-java-5.0.8-bin

好了,有兴趣的人可以试试吧,代码都经过我测试过了,虽然有些地方代码结构不是特别完整,但只是入门用而已。先有了一个成功能够运行的例子之后才有更多的心情去接着学下去,~_~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值