今天拿到一个需求,需要使用lucene 检索mysql数据库的一个通讯录表,需要支持全文全字段复合检索.
用户的表结构如下
(通讯录mysql表结构)
在网上找了一些例子,由于网上这些例子都不是基于lucene 4的,需要进行改动,这里我把这里好的代码共享一下..
本项目的例子基于 lucene 4.10 也就是lucene 4.0的最后一个版本,当前最新的版本是lucene 5.0 ,没注意看有什么改进..但是作为一个有经验的老员工来说,使用技术一定不要用最新的,刚发布的,老一点的技术更稳定,资料更多..
本项目例子需要依赖如下四个jar文件,大家自己去lucene官网下载即可
项目依赖的jar
package
com.text;
import
java.io.File;
import
java.sql.Connection;
import
java.sql.DriverManager;
import
java.sql.PreparedStatement;
import
java.sql.ResultSet;
import
java.sql.SQLException;
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.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.IndexWriterConfig.OpenMode;
import
org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import
org.apache.lucene.search.BooleanClause;
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;
//Lucene 为mysql数据库表 简历完整索引
public
class
LuceneDB {
Connection conn =
null
;
// lucene 连接mysql数据库
private
final
String URL =
"jdbc:mysql://127.0.0.1:3306/portal?useUnicode=true&characterEncoding=UTF8"
;
public
LuceneDB() {
try
{
Class.forName(
"com.mysql.jdbc.Driver"
);
conn = DriverManager.getConnection(URL,
"root"
,
"root"
);
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
catch
(SQLException e) {
e.printStackTrace();
}
}
public
Connection getConnection() {
return
this
.conn;
}
// 获取数据库连接
public
void
close() {
try
{
this
.conn.close();
}
catch
(SQLException e) {
e.printStackTrace();
}
}
// 关闭数据库连接
/**
* @param args
* @throws Exception
*/
public
static
void
main(String args[])
throws
Exception {
LuceneDB lucene =
new
LuceneDB();
IndexWriter writer =
null
;
Connection conn = lucene.getConnection();
String sql =
"SELECT * FROM pac_contact_info"
;
// 把lucene的索引文件保存到机器的磁盘
Directory dirWrite = FSDirectory.open(
new
File(
"D:\\index"
));
// lucene分析器 使用lucene默认的暂停词
Analyzer analyzer =
new
StandardAnalyzer(Version.LUCENE_4_10_4);
// 初始化写入配置
IndexWriterConfig iwc =
new
IndexWriterConfig(Version.LUCENE_4_10_4,analyzer);
iwc.setOpenMode(OpenMode.CREATE);
// 创建模式 OpenMode.CREATE_OR_APPEND 添加模式
//如果是CREATE ,每次都会重新创建这个索引,清空以前的数据,如果是append 每次都会追加,之前的不删除
//在日常的需求索引添加中,一般都是 APPEND 持续添加模式
writer =
new
IndexWriter(dirWrite, iwc);
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while
(rs.next()) {
Document doc =
new
Document();
// 该表所有的字段建立索引
doc.add(
new
Field(
"info_id"
, rs.getString(
"info_id"
), Field.Store.YES,Field.Index.ANALYZED));
doc.add(
new
Field(
"name"
, rs.getString(
"name"
), Field.Store.YES,Field.Index.ANALYZED));
doc.add(
new
Field(
"link_phone"
, rs.getString(
"link_phone"
), Field.Store.YES,Field.Index.ANALYZED));
doc.add(
new
Field(
"department"
, rs.getString(
"department"
), Field.Store.YES,Field.Index.ANALYZED));
doc.add(
new
Field(
"id_card"
, rs.getString(
"id_card"
), Field.Store.YES,Field.Index.ANALYZED));
doc.add(
new
Field(
"user_id"
, rs.getString(
"user_id"
), Field.Store.YES,Field.Index.ANALYZED));
writer.addDocument(doc);
}
rs.close();
// 关闭记录集
conn.close();
// 关闭数据库连接
// writer.optimize(); //索引优化
writer.close();
// 关闭读写器
//索引查询,通过如下2个字段进行 or 查询
Directory dir = FSDirectory.open(
new
File(
"D:\\index"
));
IndexReader reader = DirectoryReader.open(dir);
IndexSearcher searcher =
new
IndexSearcher(reader);
// 选择姓名中包含张字的记录
/* 单字段查询
* QueryParser parser = new QueryParser("name", new StandardAnalyzer());
Query query = parser.parse("三");
*/
// 选择姓名中包含张字的记录
String[] queries = { "王四", "处" };
String[] fields = { "name", "department" };
/**
* 这里需要注意的就是BooleanClause.Occur[]数组,它表示多个条件之间的关系,
* BooleanClause.Occur.MUST表示and,BooleanClause.Occur.MUST_NOT表示not,BooleanClause.Occur.SHOULD表示or.
*/
BooleanClause.Occur[] clauses = { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD };
Query query = MultiFieldQueryParser.parse(queries, fields, clauses,
new
StandardAnalyzer());
TopDocs topDocs = searcher.search(query,
2
);
ScoreDoc[] hits = topDocs.scoreDocs;
for
(
int
i =
0
; i < hits.length; i++) {
int
DocId = hits[i].doc;
Document doc = searcher.doc(DocId);
System.out.println(doc.get(
"info_id"
) +
" "
+doc.get(
"name"
) +
" "
+doc.get(
"link_phone"
) +
" "
+doc.get(
"department"
) +
" "
+doc.get(
"id_card"
) +
" "
+doc.get(
"user_id"
) +
""
);
// 张立
}
}
}
|
Lucene,作为一种全文搜索的辅助工具,为我们进行条件搜索,无论是像Google,Baidu之类的搜索引擎,还是论坛中的搜索功能,还是其它 C/S架构的搜索,都带来了极大的便利和比较高的效率
上面的例子中并没有考虑到数据库的增量索引,不过实现起来很简单,再给数据库添加一个字段 isindex ,默认为false或者为null即可,每次索引时都会过滤一下,把没有
原文地址:http://www.itmmd.com/201504/703.html