实现查询

发表时间:2017-07-18 18:59:24 浏览量( 43 ) 留言数( 0 )

学习目标:

1、了解Lucene的操作查询的类

2、掌握Lucene的检索的方法


学习过程:

上一节课我们已经建立好索引库了,下面我们就可以对这个索引库进行查询了,这里的查询相对比较简单,我们也不必过于深究。

搜索需要使用到的几个类如下:

IndexSearcher

用于搜索有IndexWriter类建立的索引

Term

最基本的搜索功能的单元,和Field对象类似,一般包含一对字符串元素:域名和文本值

Query

查询抽象类,有很多丰富的查询类可用。

QueryParse

查询解析了,可以解析一个字符串,最终生成一个Query对象。

TopDocs

一个简单指针容器,指向前Nge排名的搜索结果,保存每个结果的docuemnt的int docID,通过docID就可以获得其对应的document对象了。

完成的搜索代码如下:

   public class SearchFile {
	public void search(String indexPath, String keyWord, int repeat,
			int hitsPerPage, boolean raw, BufferedReader in) {

		String field = "contents";

		try {
			IndexReader reader = DirectoryReader.open(FSDirectory
					.open(new File(indexPath)));
			IndexSearcher searcher = new IndexSearcher(reader);
			Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_46);
			QueryParser parser = new QueryParser(Version.LUCENE_46, field,
					analyzer);

			Query query = parser.parse(keyWord);
			System.out.println("Searching for: " + query.toString(field));

			if (repeat > 0) { // repeat & time as benchmark 
				Date start = new Date();
				for (int i = 0; i < repeat; i++) {
					searcher.search(query, null, 100);
				}
				Date end = new Date();
				System.out.println("Time: " + (end.getTime() - start.getTime())
						+ "ms");
			}

			// 用户输入第几页
			doPagingSearch(in, searcher, query, hitsPerPage, raw, true);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	public static void doPagingSearch(BufferedReader in,
			IndexSearcher searcher, Query query, int hitsPerPage, boolean raw,
			boolean interactive) throws IOException {

		// 显示5页
		TopDocs results = searcher.search(query, 5 * hitsPerPage);
		ScoreDoc[] hits = results.scoreDocs;

		int numTotalHits = results.totalHits;
		System.out.println(numTotalHits + " total matching documents");

		int start = 0;
		int end = Math.min(numTotalHits, hitsPerPage);

		while (true) {
			System.out.println("开始循环");
			if (end > hits.length) {
				System.out
						.println("Only results 1 - " + hits.length + " of "
								+ numTotalHits
								+ " total matching documents collected.");
				System.out.println("Collect more (y/n) ?");
				String line = in.readLine();
				if (line.length() == 0 || line.charAt(0) == 'n') {
					break;
				}

				hits = searcher.search(query, numTotalHits).scoreDocs;
			}

			end = Math.min(hits.length, start + hitsPerPage);
			System.out.println("start:" + start + ",end:" + end);
			for (int i = start; i < end; i++) {
				if (raw) { // output raw format
					System.out.println("doc=" + hits[i].doc + " score="
							+ hits[i].score);
					continue;
				}

				Document doc = searcher.doc(hits[i].doc);
				String path = doc.get("path");
				if (path != null) {
					System.out.println((i + 1) + ". " + path);
					String title = doc.get("title");
					if (title != null) {
						System.out.println("   Title: " + doc.get("title"));
					}
					String modified = doc.get("modified");
					if (modified != null) {
						System.out.println(" content:" + modified);
					}
				} else {
					System.out.println((i + 1) + ". "
							+ "No path for this document");
				}

			}

			if (!interactive || end == 0) {
				System.out.println("结束");
				break;
			}

			if (numTotalHits >= end) {
				boolean quit = false;
				while (true) {
					System.out.print("Press ");
					if (start - hitsPerPage >= 0) {
						System.out.print("(p)revious page, ");
					}
					if (start + hitsPerPage < numTotalHits) {
						System.out.print("(n)ext page, ");
					}
					System.out
							.println("(q)uit or enter number to jump to a page.");

					String line = in.readLine();
					if (line.length() == 0 || line.charAt(0) == 'q') {
						quit = true;
						break;
					}
					// 上一页
					if (line.charAt(0) == 'p') {
						start = Math.max(0, start - hitsPerPage);
						break;
					} else if (line.charAt(0) == 'n') {
						if (start + hitsPerPage < numTotalHits) {
							start += hitsPerPage;
						}
						break;
					} else {
						int page = Integer.parseInt(line);
						if ((page - 1) * hitsPerPage < numTotalHits) {
							start = (page - 1) * hitsPerPage;
							break;
						} else {
							System.out.println("No such page");
						}
					}
				}
				if (quit)
					break;
				end = Math.min(numTotalHits, start + hitsPerPage);
			}
		}
	}

	public static void main(String[] args) throws UnsupportedEncodingException {
		
		BufferedReader hi =new BufferedReader(new InputStreamReader(System.in));
		
		SearchFile searchFile = new SearchFile();
		
		searchFile.search("d://luceneindex", "Jane",0, 10, false, hi);
	}

}

这段代码的功能比较全部,还包括了分页功能,你可以输入“N”,就可以翻页了,不过只有前面的5页的信息,要注意的是在搜索得到结果返回时,只是获得对应document的id,只有在执行hitdoc方法是才会取得其对应的值。

能够如何快速的建立索引库,并进行高效查询,恐怕和其他搜索比起来,lucene的封装是最好的,因为我们只需要使用其提供的几个类,调用几个简单的方法就可以了,当然这个过程其实是非常复杂的一个过程,不过lucene都已经帮我们封装好了。