Lucene索引库查询(五)

3/8/2017来源:ASP.NET技巧人气:2853

一、索引库的查询

对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样。Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。 可通过两种方法创建查询对象: (1)使用Lucene提供Query子类 Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,NumericRangeQuery数字范围查询等。如下代码:
Query query = new TermQuery(new Term("name", "lucene"));(2) 使用QueryParse解析查询表达式
QueryParse会将用户输入的查询表达式解析成Query对象实例。如下代码:
QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
Query query = queryParser.parse("name:lucene");

二、使用query的子类查询

2.1 TermQuery TermQuery,通过项查询,TermQuery不使用分析器,所以建议匹配不分词的Field域查询,比如订单号、分类ID号等。根据词进行搜索(只能从文本中进行搜索)。指定要查询的域和要查询的关键词:
@Test
	public void termQueryTest() throws Exception{
		Term term = new Term("fileName","lucene");
		TermQuery termQuery = new TermQuery(term); 
		Directory dir = createDirectory();
		IndexReader indexReader = createIndexReader(dir);
		IndexSearcher indexSearcher = createIndexSearcher(indexReader);
		TopDocs topdocs = indexSearcher.search(termQuery, 2);
		System.out.PRintln("=====count=====" + topdocs.totalHits);
		ScoreDoc[] scoreDocs = topdocs.scoreDocs;
		for(ScoreDoc scoreDoc : scoreDocs){
			int docID = scoreDoc.doc;
			Document document = indexReader.document(docID);
			System.out.println("fileName:" + document.get("fileName"));
			System.out.println("fileSize:" + document.get("fileSize"));
			System.out.println("fileContext:" + document.get("fileContext"));
			System.out.println("============================================================");
		}
	}



2.2 NumericRangeQuery
可以根据数值范围查询。


/**
	 * 根据数字范围查询
	 * 查询文件大小 大于100小于10000的文章
	 */
	@Test
	public void numericRangeQueryTest() throws Exception{
		//查询文件大小 大于100小于10000的文章
		//第一次参数:域名
		//第二个参数:最小值
		//第三个参数:最大值
		//第四个参数:是否包含最小值
		//第五个参数:是否包含最大值
		Query query = NumericRangeQuery.newLongRange("fileSize", 100L, 10000L, true, true);
		Directory dir = createDirectory();
		IndexReader indexReader = createIndexReader(dir);
		IndexSearcher indexSearcher = createIndexSearcher(indexReader);
		TopDocs topdocs = indexSearcher.search(query, 2);
		System.out.println("=====count=====" + topdocs.totalHits);
		ScoreDoc[] scoreDocs = topdocs.scoreDocs;
		for(ScoreDoc scoreDoc : scoreDocs){
			int docID = scoreDoc.doc;
			Document document = indexReader.document(docID);
			System.out.println("fileName:" + document.get("fileName"));
			System.out.println("fileSize:" + document.get("fileSize"));
			System.out.println("fileContext:" + document.get("fileContext"));
			System.out.println("============================================================");
		}
	}



2.3 BooleanQuery
可以组合查询条件。


@Test
	public void booleanQueryTest() throws Exception{
		
		Query numericRangeQuery = NumericRangeQuery.newLongRange("fileSize", 100L, 10000L, true, true);
		
		Term term = new Term("fileName","lucene");
		TermQuery termQuery = new TermQuery(term); 
		
		//booleanQuery,可以根据多个条件组合进行查询
		//例如:文件名称包含lucene的,并且文件大小 大于100小于10000的文章
		BooleanQuery booleanQuery = new BooleanQuery();
		
		//Occur是逻辑关键词
		//MUST:相当于and
		//MUST_NOT:相当于not
		//SHOULD:相当于or
		//注意:单独使用MUST_NOT没有任何意义
		booleanQuery.add(numericRangeQuery, Occur.MUST);
		booleanQuery.add(termQuery, Occur.MUST);
		
		Directory dir = createDirectory();
		IndexReader indexReader = createIndexReader(dir);
		IndexSearcher indexSearcher = createIndexSearcher(indexReader);
		TopDocs topdocs = indexSearcher.search(booleanQuery, 2);
		System.out.println("=====count=====" + topdocs.totalHits);
		ScoreDoc[] scoreDocs = topdocs.scoreDocs;
		for(ScoreDoc scoreDoc : scoreDocs){
			int docID = scoreDoc.doc;
			Document document = indexReader.document(docID);
			System.out.println("fileName:" + document.get("fileName"));
			System.out.println("fileSize:" + document.get("fileSize"));
			System.out.println("fileContext:" + document.get("fileContext"));
			System.out.println("============================================================");
		}
	}
2.4 MatchAllDocsQuery


使用MatchAllDocsQuery查询索引目录中的所有文档。


/**
	 * 查询所有文档
	 */
	@Test
	public void matchAllDocsQueryTest() throws Exception{
		MatchAllDocsQuery matchAllDocsQuery = new MatchAllDocsQuery();
		
		Directory dir = createDirectory();
		IndexReader indexReader = createIndexReader(dir);
		IndexSearcher indexSearcher = createIndexSearcher(indexReader);
		TopDocs topdocs = indexSearcher.search(matchAllDocsQuery, 2);
		System.out.println("=====count=====" + topdocs.totalHits);
		ScoreDoc[] scoreDocs = topdocs.scoreDocs;
		for(ScoreDoc scoreDoc : scoreDocs){
			int docID = scoreDoc.doc;
			Document document = indexReader.document(docID);
			System.out.println("fileName:" + document.get("fileName"));
			System.out.println("fileSize:" + document.get("fileSize"));
			System.out.println("fileContext:" + document.get("fileContext"));
			System.out.println("============================================================");
		}
	}




三、使用queryparser查询

通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过System.out.println(query);查询。需要使用到分析器。建议创建索引时使用的分析器和查询索引时使用的分析器要一致。根据域名进行搜索,可以设置默认搜索域,推荐使用. (只能从文本中进行搜索)。 3.1 QueryParser 需要加入queryParser依赖的jar包。
@Test
	public void QueryParserTest() throws Exception{
		Analyzer analyzer = createAnalyzer();
		QueryParser queryParser = new QueryParser("fileContext", analyzer);
		Query query = queryParser.parse("fileContext:recommended");
		Directory dir = createDirectory();
		IndexReader indexReader = createIndexReader(dir);
		IndexSearcher indexSearcher = createIndexSearcher(indexReader);
		TopDocs topdocs = indexSearcher.search(query, 2);
		System.out.println("=====count=====" + topdocs.totalHits);
		ScoreDoc[] scoreDocs = topdocs.scoreDocs;
		for(ScoreDoc scoreDoc : scoreDocs){
			int docID = scoreDoc.doc;
			Document document = indexReader.document(docID);
			System.out.println("fileName:" + document.get("fileName"));
			System.out.println("fileSize:" + document.get("fileSize"));
			System.out.println("fileContext:" + document.get("fileContext"));
			System.out.println("============================================================");
		}
	}
3.2 MulitFieldQueryParser


可以指定多个默认搜索域。


/**
	 * 从文件名称和文件内容这2个域中查询,只要含有lucene的就被查询出来
	 * @throws Exception
	 */
	@Test
	public void mulitFieldQueryParserTest() throws Exception{
		String[] fieldArray = {"fileName","fileContext"};
		Analyzer analyzer = createAnalyzer();
		MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(fieldArray,analyzer);
		Query query = multiFieldQueryParser.parse("lucene");
		
		Directory dir = createDirectory();
		IndexReader indexReader = createIndexReader(dir);
		IndexSearcher indexSearcher = createIndexSearcher(indexReader);
		TopDocs topdocs = indexSearcher.search(query, 2);
		System.out.println("=====count=====" + topdocs.totalHits);
		ScoreDoc[] scoreDocs = topdocs.scoreDocs;
		for(ScoreDoc scoreDoc : scoreDocs){
			int docID = scoreDoc.doc;
			Document document = indexReader.document(docID);
			System.out.println("fileName:" + document.get("fileName"));
			System.out.println("fileSize:" + document.get("fileSize"));
			System.out.println("fileContext:" + document.get("fileContext"));
			System.out.println("============================================================");
		}
	}

四、公用部分

public  IndexSearcher createIndexSearcher(IndexReader indexReader) {
		IndexSearcher indexSearcher = new IndexSearcher(indexReader);
		return indexSearcher;
	}
	
	public  Analyzer createAnalyzer(){
		Analyzer analyzer = new StandardAnalyzer();
		return analyzer;
	}
	
	public  Directory createDirectory() throws Exception{
		Directory directory = FSDirectory.open(new File(indexPath));
		return directory;
	}
	
	public IndexReader createIndexReader(Directory dir) throws Exception{
		@SuppressWarnings("deprecation")
		IndexReader indexReader = IndexReader.open(dir);
		return indexReader;
	}
源代码github地址:https://github.com/lucene-in-action/lucene-index-search