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

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44279753

http://www.llwjy.com/blogdetail/31bb705106379feaf6d31b58dd777be6.html

个人博客小站搭建成功,网址 www.llwjy.com,欢迎大家来吐槽~


      在前面的博客中,我们已经介绍了IndexSearcher中的检索方法,也介绍了如何基于lucene中的NRT*类去创建实时索引,在这篇博客中我们就重点介绍下基于实时索引的检索方案。在开始介绍之前,我们首先定一下检索结果的数据结构(这样做的好处是无论是什么检索,得到的数据结构都是一样的,方便以后的处理~)


原来我长这样

      检索结果的数据结构主要包括两个字段,如下:

private int count;
private List<Document> datas;


      这两个字段分别代表着该检索条件下的符合条件的记录条数和本次查询到的记录数组(该记录是索引中的记录),因此检索结果类源代码如下:

/**
 * @Description:  索引搜索结果数据结构
 */
package com.lulei.lucene.index.model;

import java.util.List;

import org.apache.lucene.document.Document;

public class SearchResultBean {
	private int count;
	private List<Document> datas;
	
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
	public List<Document> getDatas() {
		return datas;
	}
	public void setDatas(List<Document> datas) {
		this.datas = datas;
	}
}

检索原来如此简单

      检索结果介绍完了,下面就看下如何基于上次博客中的实时索引去检索数据,不知还记得上篇博客中封装的getIndexSearcher()方法(如果忘记了,看下该系列的前一篇博客),这个方法提供了当前最新可用的IndexSearcher对象,索引我们再去检索的时候,直接调用该方法即可。IndexManager类实现了另类的单例模式,使用了索引名来标识IndexManager,因此我们在写检索基类的时候,需要添加一个构造方法,如下:

public NRTSearch(String indexName) {
	indexManager = IndexManager.getIndexManager(indexName);
}
      在NRTSearch类中,我们主要封装4个方法:

1.public int getIndexNum(){}
2.public SearchResultBean search(Query query, int start, int end){}
3.public SearchResultBean search(Query query, int start, int end, Sort sort){}
4.public SearchResultBean search(int start, int count){}
      在四个方法分别实现:

1.获取索引中的记录条数;

2.根据query查询索引,根据相关读排序,返回[start, end)记录;

3.根据query查询索引,根据指定sort排序,返回[start, end)记录;

4:从索引中的第start条开始,获取后面的count条记录(如果start + count 大于索引中的记录总条数,则从头补齐)。

      这四个方法已经可以实现了80%的站内搜索功能,如果还有其他复杂的,可以根据实际情况来拓展,NRTSearch类源代码如下:

/**
 * @Description:  索引的查询操作
 */
package com.lulei.lucene.index.operation;

import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;

import com.lulei.lucene.index.manager.IndexManager;
import com.lulei.lucene.index.model.SearchResultBean;

public class NRTSearch {
	private IndexManager indexManager;
	
	/**
	 * @param indexName 索引名
	 */
	public NRTSearch(String indexName) {
		indexManager = IndexManager.getIndexManager(indexName);
	}
	
	/**
	 * @return
	 * @Author:lulei  
	 * @Description: 索引中的记录数量
	 */
	public int getIndexNum() {
		return indexManager.getIndexNum();
	}
	
	/**
	 * @param query 查询字符串
	 * @param start 起始位置
	 * @param end 结束位置
	 * @author lulei
	 * @return 查询结果
	 */
	public SearchResultBean search(Query query, int start, int end) {
		start = start < 0 ? 0 : start;
		end = end < 0 ? 0 : end;
		if (indexManager == null || query == null || start >= end) {
			return null;
		}
		SearchResultBean result = new SearchResultBean();
		List<Document> datas = new ArrayList<Document>();
		result.setDatas(datas);
		IndexSearcher searcher = indexManager.getIndexSearcher();
		try {
			TopDocs docs = searcher.search(query, end);
			result.setCount(docs.totalHits);
			end = end > docs.totalHits ? docs.totalHits : end;
			for (int i = start; i < end; i++) {
				datas.add(searcher.doc(docs.scoreDocs[i].doc));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			indexManager.release(searcher);
		}
		return result;
	}
	
	/**
	 * @param query 查询字符串
	 * @param start 起始位置
	 * @param end 结束位置
	 * @param sort 排序条件
	 * @return 查询结果
	 */
	public SearchResultBean search(Query query, int start, int end, Sort sort) {
		start = start < 0 ? 0 : start;
		end = end < 0 ? 0 : end;
		if (indexManager == null || query == null || start >= end) {
			return null;
		}
		SearchResultBean result = new SearchResultBean();
		List<Document> datas = new ArrayList<Document>();
		result.setDatas(datas);
		IndexSearcher searcher = indexManager.getIndexSearcher();
		try {
			TopDocs docs = searcher.search(query, end, sort);
			result.setCount(docs.totalHits);
			end = end > docs.totalHits ? docs.totalHits : end;
			for (int i = start; i < end; i++) {
				datas.add(searcher.doc(docs.scoreDocs[i].doc));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			indexManager.release(searcher);
		}
		return result;
	}
	
	/**
	 * @param start
	 * @param count
	 * @return
	 * @Author:lulei  
	 * @Description: 按序号检索
	 */
	public SearchResultBean search(int start, int count) {
		start = start < 0 ? 0 : start;
		count = count < 0 ? 0 : count;
		if (indexManager == null) {
			return null;
		}
		SearchResultBean result = new SearchResultBean();
		List<Document> datas = new ArrayList<Document>();
		result.setDatas(datas);
		IndexSearcher searcher = indexManager.getIndexSearcher();
		result.setCount(count);
		try {
			for (int i = 0; i < count; i++) {
				datas.add(searcher.doc((start + i) % getIndexNum()));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			indexManager.release(searcher);
		}
		return result;
	}
}
      到这里为止,NRTSearch类就介绍完毕了,之后就可以根据实际的应用来创建子类,实现一系列的查询操作,如:关键字检索、分类检索、标签检索、作者检索等等,在之后的应用中在继续介绍。

ps:最近发现其他网站可能会对博客转载,上面并没有源链接,如想查看更多关于 基于lucene的案例开发  请点击这里。或访问网址http://blog.csdn.net/xiaojimanman/article/category/2841877 或 http://www.llwjy.com/


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。