Lucene系列:(10)多條件搜索 QueryParser


一、什麼是條件搜索java

    用關健字與指定的單列或多例進行匹配的搜索apache


二、單字段條件搜索ide

QueryParser queryParser = new QueryParser(LuceneUtils.getVersion(),"content",LuceneUtils.getAnalyzer());


三、多字段條件搜索,項目中提倡多字段搜索spa

QueryParser queryParser = new MultiFieldQueryParser(LuceneUtils.getVersion(),new String[]{"content","title"},LuceneUtils.getAnalyzer());


TestSearch.java對象

package com.rk.lucene.g_search;

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

import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
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.TopDocs;
import org.junit.Test;

import com.rk.lucene.entity.Article;
import com.rk.lucene.utils.LuceneUtils;

public class TestSearch {
	@Test
	public void testAdd() throws Exception{
		List<Article> list = new ArrayList<Article>();
		list.add(new Article(1, "疾風之刃", "《疾風之刃》是一款超動做3D動漫風網遊。做爲新一代動做遊戲,《疾風之刃》呈現出極致華麗的動做表演,精心打磨出的打擊感震撼人心。"));
		list.add(new Article(2, "月光疾風", "月光疾風,日本動漫《火影忍者》中的人物,比較我的主義,性格溫和。火之國木葉村的特別上忍,中忍考試正賽預選的考官,體質彷佛很很差,有着嚴重的黑眼圈、臉色蒼白且常常咳嗽,善用劍術。"));
		list.add(new Article(3, "疾風航班中文版下載", "《疾風航班》是一款優質的動做模擬遊戲。遊戲中包括亞歐美洲,乃至飛往太空的5條航線,共計50個按部就班的關卡,以及具備挑戰性的Expert級別評定,每一個關卡結束後還可進入商店對主角和飛機進..."));
		list.add(new Article(4, "八神疾風", "八神疾風(CV:植田佳奈)是日本動漫《魔法少女奈葉A's》首次登場的女角色。暗之書事件中心人物,時空管理局魔導師,擅長貝爾卡式廣域·遠程魔法。"));
		list.add(new Article(5, "逝去的疾風", "大戰中飛得最快的日本飛機,恐怕要數「疾風」戰鬥機了,它由中島飛機廠研製生產,制式型號爲: 四式單(座)戰(鬥機),代號キ-84(讀做 Ki-84)。"));
		list.add(new Article(6, "疾風劍豪 亞索", "亞索是一個百折不屈的男人,仍是一名身手敏捷的劍客,可以運用風的力量來斬殺敵人。這位曾經春風得意的戰士由於誣陷而身敗名裂,而且被迫捲入了一場使人絕望的生存之..."));
		list.add(new Article(7, "疾風知勁草", "疾風知勁草,謂在猛烈的大風中,可看出什麼樣的草是強勁的。比喻意志堅決,經得起考驗。出自《東觀漢記·王霸傳》:「上謂霸曰:‘潁川從我者皆逝,而子獨留,始驗疾風知勁草。..."));
		LuceneUtils.addAll(list);
	}
	
	@Test
	public void testSearch() throws Exception{
		List<Article> list = new ArrayList<Article>();
		String keyword = "疾風";
		//單字段搜索
		//QueryParser queryParser = new QueryParser(LuceneUtils.getVersion(),"content", LuceneUtils.getAnalyzer());
		//多字段搜索,好處:搜索的範圍大,最大限度匹配搜索結果
		QueryParser queryParser = 
						new MultiFieldQueryParser(
								LuceneUtils.getVersion(), 
								new String[]{"content","title"}, 
								LuceneUtils.getAnalyzer());
		Query query = queryParser.parse(keyword);
		
		IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.getDirectory());
		TopDocs topDocs = indexSearcher.search(query, 10000);
		
		for(int i=0;i<topDocs.scoreDocs.length;i++){
			ScoreDoc scoreDoc = topDocs.scoreDocs[i];
			int docIndex = scoreDoc.doc;
			Document document = indexSearcher.doc(docIndex);
			System.out.println("編號爲"+document.get("id")+"號的文章得分是" + scoreDoc.score);
			
			Article article = LuceneUtils.document2javabean(document, Article.class);
			list.add(article);
		}
		indexSearcher.close();
		for(Article article : list){
			System.out.println(article);
		}
	}
}


單列搜索結果索引

編號爲1號的文章得分是0.32994816
編號爲7號的文章得分是0.28870463
編號爲4號的文章得分是0.23330858
編號爲5號的文章得分是0.23330858
編號爲2號的文章得分是0.20414501
編號爲3號的文章得分是0.20414501

多列搜索結果遊戲

編號爲1號的文章得分是0.8313483
編號爲4號的文章得分是0.76052743
編號爲2號的文章得分是0.73915535
編號爲7號的文章得分是0.72742975
編號爲5號的文章得分是0.68683356
編號爲3號的文章得分是0.5180738
編號爲6號的文章得分是0.44216305


LuceneUtils.java事件

package com.rk.lucene.utils;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
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.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
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.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import com.rk.lucene.entity.Page;

public class LuceneUtils {
	private static Directory directory;
	private static Version version;
	private static Analyzer analyzer;
	private static MaxFieldLength maxFieldLength;
	private static final String LUCENE_DIRECTORY= "D:/rk/indexDB";
	
	static{
		try {
			directory = FSDirectory.open(new File(LUCENE_DIRECTORY));
			version = Version.LUCENE_30;
			analyzer = new StandardAnalyzer(version);
			maxFieldLength = MaxFieldLength.LIMITED;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	//不讓外部new當前幫助類的對象
	private LuceneUtils(){}
	
	public static <T> void pagination(Page<T> page,String field,String keyword,Class<T> clazz) throws Exception{
		QueryParser queryParser = new QueryParser(getVersion(), field, getAnalyzer()); 
		Query query = queryParser.parse(keyword);
		
		IndexSearcher indexSearcher = new IndexSearcher(getDirectory());
		TopDocs topDocs = indexSearcher.search(query, 200);
		int totalHits = topDocs.totalHits;
		int curPage = page.getCurPage();
		int pageSize = page.getPageSize();
		int quotient = totalHits / pageSize;
		int remainder = totalHits % pageSize;
		int totalPages = remainder==0 ? quotient : quotient+1;
		int startIndex = (curPage-1) * pageSize;
		int stopIndex = Math.min(startIndex + pageSize, totalHits);
		List<T> list = page.getItems();
		if(list == null){
			list = new ArrayList<T>();
			page.setItems(list);
		}
		list.clear();
		for(int i=startIndex;i<stopIndex;i++){
			ScoreDoc scoreDoc = topDocs.scoreDocs[i];
			int docIndex = scoreDoc.doc;
			Document document = indexSearcher.doc(docIndex);
			T t = document2javabean(document, clazz);
			list.add(t);
		}
		
		page.setTotalPages(totalPages);
		page.setTotalItems(totalHits);
		indexSearcher.close();
	}
	
	public static <T> void add(T t) throws Exception{
		Document document = javabean2document(t);
		IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength());
		indexWriter.addDocument(document);
		indexWriter.close();
	}
	
	public static <T> void addAll(List<T> list) throws Exception{
		IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength());
		for(T t : list){
			Document doc = javabean2document(t);
			indexWriter.addDocument(doc);
		}
		indexWriter.close();
	}
	
	public static <T> void update(String field,String value,T t) throws Exception{
		Document document = javabean2document(t);
		IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength());
		indexWriter.updateDocument(new Term(field,value), document);
		indexWriter.close();
	}
	
	public static <T> void delete(String field,String value) throws Exception{
		IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength());
		indexWriter.deleteDocuments(new Term(field,value));
		indexWriter.close();
	}
	
	/**
	 * 刪除全部記錄
	 */
	public static void deleteAll() throws Exception {
		IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength());
		indexWriter.deleteAll();
		indexWriter.close();
	}
	
	/**
	 * 根據關鍵字進行搜索
	 */
	public static <T> List<T> search(String field,String keyword,int topN,Class<T> clazz) throws Exception{
		List<T> list = new ArrayList<T>();
		
		QueryParser queryParser = new QueryParser(getVersion(), field, getAnalyzer());
		Query query = queryParser.parse(keyword);
		
		IndexSearcher indexSearcher = new IndexSearcher(getDirectory());
		TopDocs topDocs = indexSearcher.search(query, topN);
		
		for(int i=0;i<topDocs.scoreDocs.length;i++){
			ScoreDoc scoreDoc = topDocs.scoreDocs[i];
			int docIndex = scoreDoc.doc;
			System.out.println("文檔索引號" + docIndex + ",文檔得分:" + scoreDoc.score);
			Document document = indexSearcher.doc(docIndex);
			T entity = (T) document2javabean(document, clazz);
			list.add(entity);
		}
		indexSearcher.close();
		return list;
	}
	
	/**
	 * 打印List
	 */
	public static <T> void printList(List<T> list){
		if(list != null && list.size()>0){
			for(T t : list){
				System.out.println(t);
			}
		}
	}
	
	//將JavaBean轉成Document對象
	public static Document javabean2document(Object obj) throws Exception{
		//建立Document對象
		Document document = new Document();
		//獲取obj引用的對象字節碼
		Class clazz = obj.getClass();
		//經過對象字節碼獲取私有的屬性
		java.lang.reflect.Field[] reflectFields = clazz.getDeclaredFields();
		//迭代
		for(java.lang.reflect.Field reflectField : reflectFields){
			//反射
			reflectField.setAccessible(true);
			//獲取字段名
			String name = reflectField.getName();
			//獲取字段值
			String value = reflectField.get(obj).toString();
			//加入到Document對象中去,這時javabean的屬性與document對象的屬性相同
			document.add(new Field(name, value, Store.YES, Index.ANALYZED));
		}
		//返回document對象
		return document;
	}
	
	//將Document對象轉換成JavaBean對象
	public static <T> T document2javabean(Document document,Class<T> clazz) throws Exception{
		T obj = clazz.newInstance();
		java.lang.reflect.Field[] reflectFields = clazz.getDeclaredFields();
		for(java.lang.reflect.Field reflectField : reflectFields){
			reflectField.setAccessible(true);
			String name = reflectField.getName();
			String value = document.get(name);
			BeanUtils.setProperty(obj, name, value);
		}
		return obj;
	}
	
	public static Directory getDirectory() {
		return directory;
	}

	public static void setDirectory(Directory directory) {
		LuceneUtils.directory = directory;
	}

	public static Version getVersion() {
		return version;
	}

	public static void setVersion(Version version) {
		LuceneUtils.version = version;
	}

	public static Analyzer getAnalyzer() {
		return analyzer;
	}

	public static void setAnalyzer(Analyzer analyzer) {
		LuceneUtils.analyzer = analyzer;
	}

	public static MaxFieldLength getMaxFieldLength() {
		return maxFieldLength;
	}

	public static void setMaxFieldLength(MaxFieldLength maxFieldLength) {
		LuceneUtils.maxFieldLength = maxFieldLength;
	}

}
相關文章
相關標籤/搜索