一、
项目结构
constans.java 是常量类
LuceneIndex.java 建立索引类
LuceneSearch.java 搜索类
数据文件:
package com.xin;
public class Constants {
public final static String INDEX_FILE_PATH = "e:\\lucene\\test"; //索引的文件的存放路径
public final static String INDEX_STORE_PATH = "e:\\lucene\\index"; //索引的存放位置
}
package com.xin;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Date;
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.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
/**
* @author chongxin
* @since 2013/6/19
* @version Lucene 4.3.1
* */
public class LuceneIndex {
// 索引器
private IndexWriter writer = null;
public LuceneIndex() {
try {
//索引文件的保存位置
Directory dir = FSDirectory.open(new File(Constants.INDEX_STORE_PATH));
//分析器
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
//配置类
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_40,analyzer);
iwc.setOpenMode(OpenMode.CREATE);//创建模式 OpenMode.CREATE_OR_APPEND 添加模式
writer = new IndexWriter(dir, iwc);
} catch (Exception e) {
e.printStackTrace();
}
}
// 将要建立索引的文件构造成一个Document对象,并添加一个域"content"
private Document getDocument(File f) throws Exception {
Document doc = new Document();
FileInputStream is = new FileInputStream(f);
Reader reader = new BufferedReader(new InputStreamReader(is));
//字符串 StringField LongField TextField
Field pathField = new StringField("path", f.getAbsolutePath(),Field.Store.YES);
Field contenField = new TextField("contents", reader);
//添加字段
doc.add(contenField);
doc.add(pathField);
return doc;
}
public void writeToIndex() throws Exception {
File folder = new File(Constants.INDEX_FILE_PATH);
if (folder.isDirectory()) {
String[] files = folder.list();
for (int i = 0; i < files.length; i++) {
File file = new File(folder, files[i]);
Document doc = getDocument(file);
System.out.println("正在建立索引 : " + file + "");
writer.addDocument(doc);
}
}
}
public void close() throws Exception {
writer.close();
}
public static void main(String[] args) throws Exception {
// 声明一个对象
LuceneIndex indexer = new LuceneIndex();
// 建立索引
Date start = new Date();
indexer.writeToIndex();
Date end = new Date();
System.out.println("建立索引用时" + (end.getTime() - start.getTime()) + "毫秒");
indexer.close();
}
}
执行结果:
正在建立索引 : e:\lucene\test\a.txt
正在建立索引 : e:\lucene\test\b.txt
正在建立索引 : e:\lucene\test\c.txt
正在建立索引 : e:\lucene\test\d.txt
建立索引用时109毫秒
生成的索引文件:
查找:
package com.xin;
import java.io.File;
import java.util.Date;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
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.FSDirectory;
import org.apache.lucene.util.Version;
/**
* @author chongxin
* @since 2013/6/19
* @version Lucene 4.3.1
* */
public class LuceneSearch {
// 声明一个IndexSearcher对象
private IndexSearcher searcher = null;
// 声明一个Query对象
private Query query = null;
private String field = "contents";
public LuceneSearch() {
try {
IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(Constants.INDEX_STORE_PATH)));
searcher = new IndexSearcher(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
//返回查询结果
public final TopDocs search(String keyword) {
System.out.println("正在检索关键字 : " + keyword);
try {
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
QueryParser parser = new QueryParser(Version.LUCENE_40, field,analyzer);
// 将关键字包装成Query对象
query = parser.parse(keyword);
Date start = new Date();
TopDocs results = searcher.search(query, 5 * 2);
Date end = new Date();
System.out.println("检索完成,用时" + (end.getTime() - start.getTime())
+ "毫秒");
return results;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//打印结果
public void printResult(TopDocs results) {
ScoreDoc[] h = results.scoreDocs;
if (h.length == 0) {
System.out.println("对不起,没有找到您要的结果。");
} else {
for (int i = 0; i < h.length; i++) {
try {
Document doc = searcher.doc(h[i].doc);
System.out.print("这是第" + i + "个检索到的结果,文件名为:");
System.out.println(doc.get("path"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("--------------------------");
}
public static void main(String[] args) throws Exception {
LuceneSearch test = new LuceneSearch();
TopDocs h = null;
h = test.search("中国");
test.printResult(h);
h = test.search("人民");
test.printResult(h);
h = test.search("共和国");
test.printResult(h);
}
}
二、如果要查询的是个对象,以Goods对象为例,那LuceneIndex文件中的private Document getDocument(File f)该方法就该变成private Document getDocument(Goods gosds),以下是全码
/**
* 从goods对象生成一个document对象便于建立索引
* @param goods
* @return
*/
public static Document parseDocumentFromGoods(Goods goods){
Document doc = new Document();
doc.add(new StringField("goodsId", goods.getgoodsId(), Store.YES));
doc.add(new StoredField("goodsPic", goods.getGoodsPic()));
doc.add(new LongField("addDate", Long.parseLong(goods.getGoodsAddDate()), Store.YES));
doc.add(new StringField("shopId", goods.getShopId() + "", Store.YES));
doc.add(new DoubleField("goodsPrice", goods.getGoodsPrice(), Store.YES));
doc.add(new IntField("goodsSellNum", goods.getGoodsSellNum(), Store.YES));
TextField title = new TextField("goodsName", goods.getGoodsName(), Store.YES);
title.setBoost(2.0f);
doc.add(title);
if(goods.getKeywords() != null){
TextField keywords = new TextField("keywords", goods.getKeywords(),Store.YES);
keywords.setBoost(1.5f);
doc.add(keywords);
}
<span style="white-space:pre"> </span> return doc;
}
三、删除某个索引,在luceneIndex中添加如下方法
public boolean deleteGoodsIndexById(String id){
Term t = new Term("goodsId", id);
Query q = new TermQuery(t);
try {
writer.deleteDocuments(q);
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
四、如果要查询某个对象中的索引
/**
* 根据传入的参数查询商品
*
* @param searchVo 要查询的类
* @return 返回结果,GoodsResultBean的类结构如下
<span style="white-space:pre"> public class GoodsResultBean {
private int total;
private List<Goods> goodss;
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List<Goods> getGoodss() {
return goodss;
}
public void setGoodss(List<Goods> goodss) {
this.goodss = goodss;
}
}</span>
*/
String[] goodsFields = new String[]{"goodsName"};
String[] goodsIdsFields = new String[]{"goodsId"};
String[] goodsCateFields = new String[]{"goodsClassification", "goodsType", "goodsCategoryId"};
public GoodsResultBean search(GoodsSearchVo searchVo) throws ParseException, IOException {
BooleanQuery booleanQuery = new BooleanQuery();
Query query = null;
if (searchVo.getGoodsIds() == null && searchVo.getGoodsCategory() == null && searchVo.getKey() == null && searchVo.getGoodsType() == 0 && searchVo.getGoodsClassification() == 0 && searchVo.getCategoryId() == 0) {
query = NumericRangeQuery.newLongRange("addDate", //field name
null, //min 从它开始
null,//max 到它结束
true, //是否包含min
true); //是否包含maxj
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
if (StringUtil.isNotBlank(searchVo.getGoodsCategory())) {
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_43, goodsCateFields, analyzer);
query = parser.parse(searchVo.getGoodsCategory());
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
if (StringUtil.isNotBlank(searchVo.getKey())) {
searchVo.setKey(StringUtil.getKey(searchVo.getKey()));
// 关键词组较长分词查询
// 多字段查询parser
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_43, goodsFields, analyzer);
query = parser.parse(QueryParser.escape(searchVo.getKey()));
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
if (StringUtil.isNotBlank(searchVo.getGoodsIds())) {
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_43, goodsIdsFields, analyzer);
query = parser.parse(QueryParser.escape(searchVo.getGoodsIds()));
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
if (searchVo.getCategoryId() != 0 || searchVo.getGoodsType() != 0 || searchVo.getGoodsClassification() != 0) {
if (searchVo.getCategoryId() != 0)
query = new TermQuery(new Term("goodsCategoryId", searchVo.getCategoryId() + ""));
else if (searchVo.getGoodsType() != 0)
query = new TermQuery(new Term("goodsType", searchVo.getGoodsType() + ""));
else if (searchVo.getGoodsClassification() != 0)
query = new TermQuery(new Term("goodsClassification", searchVo.getGoodsClassification() + ""));
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
if (StringUtil.isNotBlank(searchVo.getFinishedDate())) {
query = new TermQuery(new Term("finishedDate", searchVo.getFinishedDate()));
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
if (searchVo.getMaxPrice() != 0 || searchVo.getMinPrice() != 0) {
query = NumericRangeQuery.newDoubleRange("goodsPrice", searchVo.getMinPrice() == 0 ? null : searchVo.getMinPrice(), searchVo.getMaxPrice() == 0 ? null : searchVo.getMaxPrice(), true, true);
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
if (StringUtil.isNotBlank(searchVo.getOrigin())) {
query = new TermQuery(new Term("origin", searchVo.getOrigin()));
booleanQuery.add(query, BooleanClause.Occur.MUST);
}
GoodsResultBean goodsResultBean;
if(searchVo.getPriceOrder() != 0) {
goodsResultBean = priceSearch(searchVo, query);
} else if(searchVo.getTimeOrder() != 0) {
goodsResultBean = addDateSearch(searchVo,query);
} else if(searchVo.getSales() != 0) {
goodsResultBean = sellNumSearch(searchVo,query);
} else {
goodsResultBean = defaultSearch(searchVo, booleanQuery);
}
return goodsResultBean;
}