您的位置:首页 > 数据库

lucene3.6分页、自定义查询的数据库实现

2013-04-03 10:24 288 查看
大家好,小鸟前段时间有点忙啊,大概有一个多星期没有更新博客了,主要是最近公司赶进度,小鸟每天加班啊,不过还是乐意和大家分享一下小鸟最近的成果的,最近小鸟使用了lucene,感觉还不错哦,来和大家探讨一下,求指教啊!

public class LuceneUtil {

private List<ProductBySearch> productList = new ArrayList();

private File indexpath = null;

private String sql = null;

private String condition = null;

private String updateField = null;

private String updateValue = null;

private SearchConfig sc = null;

public LuceneUtil() {

sc = new SearchConfig();

indexpath = sc.getIndexPath();

sql = sc.getSql();

condition = sc.getCondition();

updateField = sc.getUpdateField();

updateValue = sc.getUpdateValue();

if(!updateValue.equals("")){

sql = sql + " where " + updateField + " > " + updateValue;

}

}

public void createIndex() throws Exception{

System.out.println("==========正在生成数据库索引。");

//把数据库中的数据查询出来

String driver = "com.mysql.jdbc.Driver";

String uname = "数据库用户名";

String password = "数据库密码";

Class.forName(driver).newInstance();

Connection connection = DriverManager.getConnection("数据库连接地址", uname, password);

PreparedStatement pstmt = connection.prepareStatement(sql);

ResultSet rs = pstmt.executeQuery();

try {

//打开索引文件

FSDirectory directory = FSDirectory.open(indexpath);

Analyzer analyzer = new IKAnalyzer();

IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,analyzer);

indexWriterConfig.setOpenMode(OpenMode.CREATE);

IndexWriter writer = new IndexWriter(FSDirectory.open(indexpath),

indexWriterConfig);

while (rs.next()) {

Document doc = new Document();

doc.add(new Field("id", String.valueOf(rs.getInt("id")),

Field.Store.YES, Field.Index.ANALYZED));

doc.add(new Field("description", String.valueOf(rs.getString("description")),

Field.Store.YES, Field.Index.ANALYZED));

doc.add(new Field("img_url", rs.getString("img_url"), Field.Store.YES,

Field.Index.ANALYZED));

doc.add(new Field("product_name", rs.getString("product_name"), Field.Store.YES,

Field.Index.NOT_ANALYZED));

doc.add(new Field("rack_status", rs.getString("rack_status"), Field.Store.YES,

Field.Index.ANALYZED));

doc.add(new Field("extra_time",String.valueOf( rs.getInt("extra_time")), Field.Store.YES,

Field.Index.ANALYZED));

doc.add(new Field("on_sale", String.valueOf( rs.getInt("on_sale")), Field.Store.YES,

Field.Index.ANALYZED));

doc.add(new Field("bname", rs.getString("b.name"), Field.Store.YES,

Field.Index.ANALYZED));

doc.add(new Field("tname", rs.getString("t.name"), Field.Store.YES,

Field.Index.ANALYZED));

writer.addDocument(doc);

}

writer.close();

directory.close();

} catch (Exception e) {

e.printStackTrace();

}

}

public List<Document> search(String keyword,int pageSize,int pageNo) {

List<Document> list = new ArrayList<Document>();

try {

FSDirectory directory = FSDirectory.open(indexpath);

IndexReader reader = IndexReader.open(directory);

IndexSearcher isearcher = new IndexSearcher(reader);

isearcher.setSimilarity(new IKSimilarity());

if(keyword == null || keyword.equals("")){

return list;

}

Query query = IKQueryParser.parseMultiField("product_name,bname,tname".split(","), keyword);

// 实现分页搜索,注释的为使用lucene内部的排序

// TopDocs topDocs = isearcher.search(query, (pageNo+1)*pageSize,new Sort(new SortField("product_name",SortField.STRING,true)));

//红色的部分为实现自定义排序的类,该类代码下面可见

TopDocs topDocs = isearcher.search(query, (pageNo+1)*pageSize,new Sort(new SortField[]{new SortField("product_name",new ProductSortComparator(2))}));

int start = pageSize*(pageNo-1);

int end = topDocs.totalHits>start+pageSize?start+pageSize:topDocs.totalHits;

// 输出结果

ScoreDoc[] scoreDocs = topDocs.scoreDocs;

for (int i = start; i < end; i++) {

Document targetDoc = isearcher.doc(scoreDocs[i].doc);

list.add(targetDoc);

}

isearcher.close();

reader.close();

directory.close();

isearcher.close();

} catch (Exception e) {

e.printStackTrace();

}

return list;

}

public List<ProductBySearch> ducments2ProductList(List<Document> docs) {

for(Document doc : docs){

ProductBySearch productBySearch = new ProductBySearch();

productBySearch.setId(Integer.parseInt(doc.get("id")));

productBySearch.setDescription(doc.get("description"));

productBySearch.setProduct_name(doc.get("product_name"));

productBySearch.setRack_status(doc.get("rack_status"));

productBySearch.setExtra_time(doc.get("extra_time"));

productBySearch.setOn_sale(doc.get("on_sale"));

productBySearch.setImg_url(doc.get("img_url"));

productBySearch.setBrand_name(doc.get("bname"));

productBySearch.setProductType_name(doc.get("tname"));

productList.add(productBySearch);

}

return productList;

}

public static void main(String[] args) throws Exception {

LuceneUtil lu = new LuceneUtil();

lu.createIndex();

List<Document> docs = lu.search("豆瓣",5,1);

List<ProductBySearch> plist = lu.ducments2ProductList(docs);

for(ProductBySearch pro : plist){

System.out.println(pro);

}

}

}

以下类为实现自定义排序的类:

*****************************************************************************************************

import java.io.IOException;

import org.apache.lucene.index.IndexReader;

import org.apache.lucene.search.FieldCache;

import org.apache.lucene.search.FieldComparator;

import org.apache.lucene.search.FieldComparatorSource;

public class ProductSortComparator extends FieldComparatorSource {

private static final long serialVersionUID = 1L;

private int orderBy;

public ProductSortComparator() {

}

public ProductSortComparator(int orderBy) {

this.orderBy = orderBy;

}

@Override

public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {

return new DistanceSourceLookupComparator(fieldname, numHits);

}

private class DistanceSourceLookupComparator extends FieldComparator {

private String[] currentProductsValue;

private String[] values;

private String bottom;

String fieldName;

public DistanceSourceLookupComparator(String fieldName, int numHits) {

values = new String[numHits];

this.fieldName = fieldName;

}

public int letterToCode(String str) {

char[] chrs = str.toLowerCase().toCharArray();

int code = (int) chrs[0];

return code;

}

@Override

public int compare(int slot1, int slot2) {

switch (orderBy) {

case 1:// a--z

if (letterToCode(values[slot1]) > letterToCode(values[slot2]))

return 1;

if (letterToCode(values[slot1]) < letterToCode(values[slot2]))

return -1;

break;

case 2:// z---a

if (letterToCode(values[slot1]) < letterToCode(values[slot2]))

return 1;

if (letterToCode(values[slot1]) > letterToCode(values[slot2]))

return -1;

break;

default:

return 0;

}

return 0;

}

@Override

public void setBottom(int slot) {

this.bottom = values[slot];

}

@Override

public int compareBottom(int doc) throws IOException {

String str = currentProductsValue[doc];

switch (orderBy) {

case 1:

if (letterToCode(bottom) < letterToCode(str))

return -1;

if (letterToCode(bottom) > letterToCode(str))

return 1;

break;

case 2:

if (letterToCode(bottom) > letterToCode(str))

return -1;

if (letterToCode(bottom) < letterToCode(str))

return 1;

default:

return 0;

}

return 0;

}

@Override

public void copy(int slot, int doc) throws IOException {

values[slot] = currentProductsValue[doc];

}

@Override

public void setNextReader(IndexReader reader, int docBase) throws IOException {

currentProductsValue = FieldCache.DEFAULT.getStrings(reader, "product_name");

}

@Override

public Object value(int slot) {

return new String(values[slot]);

}

}

}

以上为使用的建立索引的方法,查询方法和测试方法,接下来的类为一个读取配置文件的类

****************************************************************************************************************************

public class SearchConfig {

private Properties searchPro;

private String searchFile = "E:/download/lucene/lucene/src/main/java/com/njtcedu/lucene/search.properties";

private String SQL = "sql";

private String CONDITION = "search.condition";

private String INDEX = "index.path";

public SearchConfig(){

initSearch();

}

public void initSearch(){

searchPro = new Properties();

try {

searchPro.load(new FileInputStream(searchFile));

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public String getSql(){

return searchPro.getProperty(SQL, "");

}

public String getCondition(){

return searchPro.getProperty(CONDITION, "");

}

public File getIndexPath(){

String path = searchPro.getProperty(INDEX, "");

File file = new File(path);

if (!file.exists()) {

file.mkdir();

}

return file;

}

public long getPeriod(){

String period = searchPro.getProperty("period", "0");

return Integer.valueOf(period);

}

public String getUpdateField(){

return searchPro.getProperty("update.field", "");

}

public String getUpdateValue(){

return searchPro.getProperty("update.value", "");

}

}

*************************************************************************************

配置文件的内容为:

sql=select p.id, p.description, p.img_url,p.product_name,p.rack_status,p.extra_time,p.on_sale, b.name,t.name from products.product p join products.brand b on p.brand_id = b.id join products.producttype t on p.product_type_id = t.id order by p.product_name

search.condition=product_name,bname,tname

index.path=D:/luceneindex

period=10000

**********************************************************************************************************************************************

sql就是你想建立索引的字段,即查询出来的结果集,condition为你想检索的字段,分词器我使用的是Ik,测试结果如下,欢迎大家交流哦:

==========正在生成数据库索引。

ProductBySearch [id=5, description=我的商品, img_url=/product/ec356f16-ea38-4734-baf6-9a9f920d7e72_full.jpg, product_name=Absa, rack_status=Y, extra_time=0, on_sale=0, brand_name=老干妈豆瓣酱, productType_name=A模板]

ProductBySearch [id=17, description=, img_url=/product/2ad13e54-6bb6-4fcf-bcdb-587c09a9f3bc_full.jpg, product_name=ada, rack_status=Y, extra_time=1, on_sale=1, brand_name=老干妈豆瓣酱, productType_name=Test]

ProductBySearch [id=14, description=dawdawda, img_url=/product/a3d0019d-0c65-4f34-8038-761efb9e5af4_full.jpg, product_name=awdawd, rack_status=N, extra_time=122, on_sale=1, brand_name=老干妈豆瓣酱, productType_name=电脑]

ProductBySearch [id=19, description=, img_url=/product/3857d4a3-d892-4e6a-9b13-3b769c9c9461_full.jpg, product_name=badasdas, rack_status=N, extra_time=0, on_sale=1, brand_name=老干妈豆瓣酱, productType_name=Test]

ProductBySearch [id=6, description=, img_url=/product/6ed33ee6-907f-4e3e-889b-f12bd79980dd_full.jpg, product_name=Bestjimliu, rack_status=N, extra_time=2, on_sale=1, brand_name=老干妈豆瓣酱, productType_name=Test]

ProductBySearch [id=12, description=fawfawfaw, img_url=/product/36b0c120-9077-440b-a906-1e6527d539b5_full.jpg, product_name=dawdwa, rack_status=Y, extra_time=11, on_sale=1, brand_name=老干妈豆瓣酱, productType_name=Test]

ProductBySearch [id=11, description=dawdawda, img_url=/product/2a842120-66af-4d70-85cb-ac23827a2a1d_full.jpg, product_name=wawaaw, rack_status=Y, extra_time=11, on_sale=1, brand_name=老干妈豆瓣酱, productType_name=Test]

ProductBySearch [id=23, description=爱的色放, img_url=/product/d21cbf26-e959-4fb6-a88c-a073766660a1_full.jpg, product_name=还达芙妮, rack_status=N, extra_time=0, on_sale=0, brand_name=老干妈豆瓣酱, productType_name=CheckBox]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐