课程计划:

1. 什么是全文检索,如何实现全文检索
2. Lucene实现全文检索的流程
	* 创建索引
	* 查询索引
3. 配置开发环境
4. 入门程序
5. 分析器的分析过程
	1. 测试分析器的分析效果
	2. 第三方中文分析器
6. 索引库维护
	1. 添加文档
	2. 删除文档
	3. 修改文档
7. 索引库查询
	1. 使用Query子类查询
	2. 使用QueryParser查询

全文检索概述

1. 数据分类:
	1. 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。			[数据类型固定]
	2. 非结构化数据:指不定长或无固定格式的数据。如邮件,word文档等磁盘上的文件		[数据类型不固定]
2. 结构化数据搜索:
	1. 常见的结构化数据也就是数据库中的数据。   使用sql语句进行查询,很快得到结果
	2. 为什么数据库搜索很容易?
		* 因为数据库中的数据存储是有规律的,有行有列而且数据格式、数据长度都是固定的。
		* [简单,速度快]
3. 非结构化数据查询方法:
	1. 顺序扫描法:
		* 所谓的顺序扫描,比如要找内容包含一个字符串,就是一个文档一个文档的看,如果此文档包含此字符串则为我们要找的文件,借着看下一个文件,直到扫描所有的文件。利用windows的搜索也可以搜索文件内容,只是相当的慢。
	2. 全文检索 [把非结构化数据变成结构化数据]:
		1. 概述:
			* 将结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此结构进行搜索,从而达到搜索相对较快的目的。
		2. 索引:
			* 这部分从非结构化数据中提取出的然后重新组织的信息,我们称之为索引。
		3. 分析:
			* 先根据空格进行字符串拆分,得到一个单词列表,基于单词列表创建一个索引。然后查询索引,根据单词和文档的对应关系找到文档列表,这个过程就叫做全文检索。
			* 查询的时候,先查询索引表,通过关键字与坐标对应找到该关键字的坐标,再通过坐标查询存有关键字的表,速度很快。
			* 树形结构;
		4. 总结:
			* 这种先创建索引然后查询索引的过程就叫做全文检索。
			* 索引一次创建,多次使用,表现为每次查询速度很快;
			* 以id为主键,[唯一]使用主键作为查询条件速度很快。
		5. 注意:
			1. 并不是所有的表都需要建立索引,尤其是有增删改;
			2. 只查询的数据可以用来建立索引;
4. 如何实现全文检索:
	* 可以使用 Lucene 实现全文检索。Lucene 是 apache 下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene 的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
5. 应用场景:
	* 对于数据量大、数据结构不固定的数据可采用全文检索方式搜索,比如百度、Google 等搜索引擎、论坛站内搜索、电商网站站内搜索等。
	* 举例:
		1. 搜索引擎:     百度,360搜索,谷歌,搜狗
		2. 站内搜索:		 论坛搜索,微博,文章搜索
		3. 电商搜索:		淘宝搜索,京东搜索
6. 种类:
	1. lucene
		* 它是已经被淘汰的全文检索技术,学习它是为了学习全文检索原理;
	2. ElasticSearch
		* 它在学成在线项目中有讲解,它是最新的技术,使用率日益增加;
	3. solr
		* 它在品优购项目中有讲解

lucene

1. 什么是Lucene?
	* Lucene是一个基于java开发全文检索工具包。
2. Lucene实现全文检索的流程
	1. 创建索引
		1. 获得文档
			* 原始文档:要基于那些数据来进行搜索,那么这些数据就是原始文档。
				* 原始文档是指要索引和搜索的内容。原始内容包括互联网上的网页、数据库中的数据、磁盘上的文件等。
			* 搜索引擎:使用爬虫获得原始文档。
				* 目的:信息采集的目的是为了对原始内容进行索引。
			* 站内搜索:数据库中的数据。
				* 我们要获取磁盘上文件的内容,可以通过文件流来读取文本文件的内容,对于pdf、doc、xls 等文件可通过第三方提供的解析工具读取文件内容,比如 Apache POI 读取 doc和 xls 的文件内容。

			* 案例:直接使用io流读取磁盘上的文件,直接获得原始文档
		2. 构建文档对象:
			1. 获取原始内容的目的是为了索引,在索引前需要将原始内容建成文档(Document),文档中包括一个一个的域(Field),域中储存内容。
			2. 这里我们可以将磁盘上的一个文件当成一个document,Document中包括一些Filed(file_name文件名称,file_path文件路径,file_size文件大小,file_content文件内容);
			3. 域中保存就是原始文档数据
				* 域的名称
				* 域的值
			4. 注意:每个Document可以有多个Field,同一个Document可以有相同的Field(域名和域值都相同),每个文档都有一个唯一的编号,就是文档id;
		3. 分析文档:
			1. 就是分词的过程
				1. 根据空格进行字符串拆分,得到一个单词列表
				2. 把单词统一转换为小写
				3. 去除标点符号
				4. 去除停用词
					* 停用词: 无意义的词;
					* 每个关键词都封装成一个Term对象中
						* Term中包含两部分内容
							* 关键词所在的域
							* 关键词本身
						* 不同的域中拆分出来的相同的关键词是不同的Term。
		4. 创建索引:
			1. 基于关键词列表创建一个索引。保存到索引库中;
			2. 索引库中:
				1. 索引
				2. document对象
				3. 关键词和文档的对应关系
			3. 倒排索引结构:通过词语找文档
	2. 查询索引:
		1. 用户查询接口
			1. 用户输入查询条件的地方
			2. 例如:百度的搜索框
		2. 把关键词封装成一个查询对象;
			1. 要查询的域
			2. 要搜索的关键词
		3. 执行查询
			1. 根据要查询的关键词到对应的域上进行搜索。
			2. 找到关键词,根据关键词找到对应的文档。
		4. 渲染结果
			1. 根据文档的id找到文档对象
			2. 对关键词进行高亮显示
			3. 分页处理
			4. 最终展示给用户看

3. 过程:
	1. 索引过程:对搜索的原始内容进行索引构建一个索引库,索引过程包括:
		* 确定原始内容即要搜索的内容->采集文档->创建文档->分析文档->索引文档
	2. 搜索过程:从索引库中搜索内容,搜索过程包括:
		* 用户通过搜索界面->创建查询->执行搜索,从索引库搜索->渲染搜索结果

入门程序

1. 创建索引
	* 环境:
		1. 下载
			* http://lucene.apache.org/
			* 最低要求:JDK1.8
		2. 解压缩
		3. 文件含义:
			1. core文件夹:  核心
			2. analysis->lucene-analyzers-common-7.4.0.jar :  分析
		4. 搭建:
			1. 创建一个java工程
			2. 添加jar:
				* lucene-analyzers-common-7.4.0.jar
				* lucene-core-7.4.0.jar
				* commons-io.jar
		5. 开始环境搭建:
			1. 创建一个java空项目
				* 创建一个Modules模块,选择"JAVA" ;		[JDK必须在1.8以上]
		   	2. 新建一个目录:lib
				* 添加上面的jar包
				* Dependencies->添加导入依赖
	* 步骤:
		1. 创建一个Director对象,指定索引库保存的位置
		2. 基于Directory对象创建一个IndexWriter对象
		3. 读取磁盘上的文件,对应每个文件创建一个文档对象
		4. 向文档对象中添加域
		5. 把文档对象写入索引库
		6. 关闭indexWriter对象

2. 开始
	1. 创建一个LuceneFirst类:
				 
		public class LuceneFirst {
		    @Test
		    public void createIndex() throws Exception {
		        //1、创建一个Director对象,指定索引库保存的位置。
		        //把索引库保存在内存中
		        //Directory directory = new RAMDirectory();
		        //把索引库保存在磁盘
		        Directory directory = FSDirectory.open(new File("C:\\temp\\index").toPath());
		        //2、基于Directory对象创建一个IndexWriter对象
		        IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());
		        //3、读取磁盘上的文件,对应每个文件创建一个文档对象。
		        File dir = new File("C:\\A0.lucene2018\\05.参考资料\\searchsource");
		        File[] files = dir.listFiles();
		        for (File f :
		                files) {
		            //取文件名
		            String fileName = f.getName();
		            //文件的路径
		            String filePath = f.getPath();
		            //文件的内容
		            String fileContent = FileUtils.readFileToString(f, "utf-8");
		            //文件的大小
		            long fileSize = FileUtils.sizeOf(f);
		            //创建Field
		            //参数1:域的名称,参数2:域的内容,参数3:是否存储
		            Field fieldName = new TextField("name", fileName, Field.Store.YES);
		            //Field fieldPath = new TextField("path", filePath, Field.Store.YES);
		            Field fieldPath = new StoredField("path", filePath);
		            Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
		            //Field fieldSize = new TextField("size", fileSize + "", Field.Store.YES);
		            Field fieldSizeValue = new LongPoint("size", fileSize);
		            Field fieldSizeStore = new StoredField("size", fileSize);
		            //创建文档对象
		            Document document = new Document();
		            //向文档对象中添加域
		            document.add(fieldName);
		            document.add(fieldPath);
		            document.add(fieldContent);
		            //document.add(fieldSize);
		            document.add(fieldSizeValue);
		            document.add(fieldSizeStore);
		            //5、把文档对象写入索引库
		            indexWriter.addDocument(document);
		        }
		        //6、关闭indexwriter对象
		        indexWriter.close();
		    }


	2. 使用luke查看索引库中的内容
		1. 资料->luke-javafx-7.4.0-luke-reale
		2. 解压后双击打开	[最低运行版本:jdk1.9]
		3. 在name中不同类中的分词出来的词即便是一样的,其类型还是不一样。比如标题名叫apache和内容中包含apache,这里的两个apache不一样;
		4. 查询:
			1.  *:* ,它表示查询全部;
		5. 使用此工具用于测试和查看,实际工作中我们还是需要用程序来完成这些操作,接下来继续我们的入门程序;
		

	3. 查询索引库
		1. 步骤:
			1. 创建一个Director对象,指定索引库的位置;
			2. 创建一个IndexReader对象
			3. 创建一个IndexSearcher对象,构造方法中的参数就是indexReader对象。
			4. 创建一个Query对象,TermQuery		[它的意思就是根据关键词查询]
			5. 执行查询,得到一个TopDocs对象
			6. 取查询结果的总记录数。
			7. 取文档列表
			8. 打印文档中的内容
			9. 关闭indexReader对象
		2. 实现:
			 * 继续在LuceneFirst类中写:	 
			 * public class LuceneFirst {
			 * ....
			 
			  @Test
			    public void searchIndex() throws Exception {
			        //1、创建一个Director对象,指定索引库的位置
			        Directory directory = FSDirectory.open(new File("C:\\temp\\index").toPath());
			        //2、创建一个IndexReader对象
			        IndexReader indexReader = DirectoryReader.open(directory);
			        //3、创建一个IndexSearcher对象,构造方法中的参数indexReader对象。
			        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
			        //4、创建一个Query对象,TermQuery
			        Query query = new TermQuery(new Term("name", "spring"));
			        //5、执行查询,得到一个TopDocs对象
			        //参数1:查询对象 参数2:查询结果返回的最大记录数
			        TopDocs topDocs = indexSearcher.search(query, 10);
			        //6、取查询结果的总记录数
			        System.out.println("查询总记录数:" + topDocs.totalHits);
			        //7、取文档列表
			        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
			        //8、打印文档中的内容
			        for (ScoreDoc doc :
			                scoreDocs) {
			            //取文档id
			            int docId = doc.doc;
			            //根据id取文档对象
			            Document document = indexSearcher.doc(docId);
			            System.out.println(document.get("name"));
			            System.out.println(document.get("path"));
			            System.out.println(document.get("size"));
			            //System.out.println(document.get("content"));
			            System.out.println("-----------------寂寞的分割线");
			        }
			        //9、关闭IndexReader对象
			        indexReader.close();
			    }
			
	
	4.分析器
		1. 默认使用的数标准分析器StandardAnalyzer
		2. 查看分析器的分析效果
			1. 使用Analyzer对象的tokenStream方法返回一个TokenStream对象,词对象中包含了最终分词结果。
			2. 实现步骤:
				1. 创建一个Analyzer对象,StandarAnalyzer对象
				2. 使用分析器对象的tokenStream方法获得一个TokenStream对象
				3. 向TokenStream对象中设置一个引用,相当于数一个指针;
				4. 调用TokenStream对象的rest方法,如果不调用抛异常
				5. 使用while循环遍历TokenStream对象
				6. 关闭TokenStream对象
	
	
		3. 实现:
		 	 * 继续在LuceneFirst类中写:	 
			 * public class LuceneFirst {
			 * ....
			 * Test
			    @Test
			    public void testTokenStream() throws Exception {
			        //1)创建一个Analyzer对象,StandardAnalyzer对象
					 Analyzer analyzer = new StandardAnalyzer();
			        //2)使用分析器对象的tokenStream方法获得一个TokenStream对象
			        TokenStream tokenStream = analyzer.tokenStream("", "2017年12月14日 - 传智播客Lucene概述公安局Lucene是一款高性能的、可扩展的信息检索(IR)工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。");		
			        //3)向TokenStream对象中设置一个引用,相当于数一个指针
			        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
			        //4)调用TokenStream对象的rest方法。如果不调用抛异常
			        tokenStream.reset();
			        //5)使用while循环遍历TokenStream对象
			        while(tokenStream.incrementToken()) {
			            System.out.println(charTermAttribute.toString());
			        }
			        //6)关闭TokenStream对象
			        tokenStream.close();

中文分析器

1. 标准分析器的缺点:
	1. 默认分词器是美国的一个程序员开发的,分词为英文的时候,以空格为分隔点,然后拆分成各个单词,中文只支持一个汉字一个关键字,准确度并不高,所以不适用;所以我们必须要使用中文分析器对其进行分析。
2. IK分词器
	* 在词语被分词的时候,它被分词成几个部分
	* 在搜索的时候,分词器拿到value值,并将其也分成几个部分
	* 然后几个部分找几个部分,按照关联度高地进行排列;

3. IKAnalyze的使用方法
	1. 把IKAnalyzer的jar包添加到工程中
	2. 把配置文件和扩展词典添加到工程的classpath下;
	3. 注意:
		* 扩展词典严禁使用windows记事本编辑,否则会使扩展词典不生效;
		* 必须保证编写的格式是utf-8    [windows记事本的utf-8不是标准的utf-8,它是utf-8+BOM,不是纯的utf-8];
		* 可以使用notepad++等编辑.
	4. 扩展词典[hotword.dic]: 添加一些日新月异的新词/公司名称等...
	5. 停用词词典[stopword.dic]: 无意义的词/敏感词等


4. 演示中文分析器的使用方法:
	1. 将IK-Analyzer...jar包导入
	2. 将配置文件,扩展词典,停用词典放入该包下:com.itheima.lucene
	3. 实现:
	 	 * 继续在LuceneFirst类中写:	 
		 * public class LuceneFirst {
		 * ....
		 * Test
		    @Test
		    public void testTokenStream() throws Exception {
		        //1)创建一个Analyzer对象,StandardAnalyzer对象
				// Analyzer analyzer = new StandardAnalyzer();		英文分析器
		        Analyzer analyzer = new IKAnalyzer();		中文分析器
		        //2)使用分析器对象的tokenStream方法获得一个TokenStream对象
		        TokenStream tokenStream = analyzer.tokenStream("", "2017年12月14日 - 传智播客Lucene概述公安局Lucene是一款高性能的、可扩展的信息检索(IR)工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。");
		        //3)向TokenStream对象中设置一个引用,相当于数一个指针
		        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
		        //4)调用TokenStream对象的rest方法。如果不调用抛异常
		        tokenStream.reset();
		        //5)使用while循环遍历TokenStream对象
		        while(tokenStream.incrementToken()) {
		            System.out.println(charTermAttribute.toString());
		        }
		        //6)关闭TokenStream对象
		        tokenStream.close();
5. 在代码中使用分析器
	1. 实现:
					 
	public class LuceneFirst {
	    @Test
	    public void createIndex() throws Exception {
	        //1、创建一个Director对象,指定索引库保存的位置。
	        //把索引库保存在内存中
	        //Directory directory = new RAMDirectory();
	        //把索引库保存在磁盘
	        Directory directory = FSDirectory.open(new File("C:\\temp\\index").toPath());
	        //2、基于Directory对象创建一个IndexWriter对象
	        IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
	        IndexWriter indexWriter = new IndexWriter(directory, config);
	        //3、读取磁盘上的文件,对应每个文件创建一个文档对象。
	        File dir = new File("C:\\A0.lucene2018\\05.参考资料\\searchsource");
	        File[] files = dir.listFiles();
	        for (File f :
	                files) {
	            //取文件名
	            String fileName = f.getName();
	            //文件的路径
	            String filePath = f.getPath();
	            //文件的内容
	            String fileContent = FileUtils.readFileToString(f, "utf-8");
	            //文件的大小
	            long fileSize = FileUtils.sizeOf(f);
	            //创建Field
	            //参数1:域的名称,参数2:域的内容,参数3:是否存储
	            Field fieldName = new TextField("name", fileName, Field.Store.YES);
	            //Field fieldPath = new TextField("path", filePath, Field.Store.YES);
	            Field fieldPath = new StoredField("path", filePath);
	            Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
	            //Field fieldSize = new TextField("size", fileSize + "", Field.Store.YES);
	            Field fieldSizeValue = new LongPoint("size", fileSize);
	            Field fieldSizeStore = new StoredField("size", fileSize);
	            //创建文档对象
	            Document document = new Document();
	            //向文档对象中添加域
	            document.add(fieldName);
	            document.add(fieldPath);
	            document.add(fieldContent);
	            //document.add(fieldSize);
	            document.add(fieldSizeValue);
	            document.add(fieldSizeStore);
	            //5、把文档对象写入索引库
	            indexWriter.addDocument(document);
	        }
	        //6、关闭indexwriter对象
	        indexWriter.close();
	    }

索引库维护

1. 域的类型:
	1. StringField(FieldName,FieldValue,Store.YES):
		* 这个用来构造Field,不分析,会将整个储存在索引中,比如姓名,身份证,订单编号等不需要分词;		
		* 不分词,建索引,存储/不存储				
		* [有些可能不需要存储,注意:不存储不代表不建索引库,搜整条数据依然可以找到它]
	2. LongPoint(String name,long...Point):
		* 可以使用LongPoint/IntPoint等类型存储数据类型的数据		
		* 分词,建索引,不存储
		* 如果需要储存数据还需要使用StoreField
	3. StoreField(FieldName,FieldValue):
		* 这个Field用来构建不同类型Field
		* 不分析,不索引,但要Field要储存在文档中
	4. TextField(FieldName,FieldValue,Store.No)或TextField(FieldName,reader)
		* 如果是一个Reader,lucene猜测内容比较多,会采用Unstored的策略;

	5. 注意:
		* 如果没有建索引,有储存,那么可以查询到该内容,但是内容中没有该关键词数据;
2. 添加文档,改造:

	Field fieldName = new TextField("name", fileName, Field.Store.YES);
   	
    Field fieldPath = new StoredField("path", filePath);
    Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
  
    Field fieldSizeValue = new LongPoint("size", fileSize);
    Field fieldSizeStore = new StoredField("size", fileSize);

	添加域:
		document.add(fieldName);
		document.add(fieldPath);
		document.add(fieldContent);
				  
		document.add(fieldSizeValue);
		document.add(fieldSizeStore);

3. 索引库维护-添加
	1. 新建一个类:IndexManger
		* public class IndexManger{
		* 
		// 添加索引
		@Test
		public void addDocument() throws Exception {
		// 索引库存放路径
		Directory directory = FSDirectory.open(new File("D:\\temp\\index").toPath());
		IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
		// 创建一个 indexwriter 对象
		IndexWriter indexWriter = new IndexWriter(directory, config);
		// 创建一个 Document 对象
		Document document = new Document();
		// 向 document 对象中添加域。
		// 不同的 document 可以有不同的域,同一个 document 可以有相同的域。
		document.add(new TextField("filename", " 新添加的文档", Field.Store.YES));
		document.add(new TextField("content", " 新添加的文档的内容", Field.Store.NO));
		//LongPoint 创建索引
		document.add(new LongPoint("size", 1000l));
		//StoreField 存储数据
		document.add(new StoredField("size", 1000l));
		// 不需要创建索引的就使用 StoreField 存储
		document.add(new StoredField("path", "d:/temp/1.txt"));
		// 添加文档到索引库
		indexWriter.addDocument(document);
		// 关闭 indexwriter
		indexWriter.close();
		}









4. 索引库维护-删除	
	* 删除文档有两种方式:
		1. 删除全部
		2. 根据查询,修改
	* 示例:
		* 继续上面的添加类...
		* @Test
		* public void deleteAllDocument() throws Exception{
		* //删除全部文档
		* indexWriter.deleteAll();
		* //indexWriter.close();
		* }
		* @Test
		* public void deleteDocumentByQuery() throws Exception{
		* //如果删除了索引库,需要先建立索引库再查询
		* indexWriter.deleteDocuments(new Term("name","apache"))
		* indexWriter.close();
		* }
5. 索引库维护-更新	
	* 特点:先删除原来的,然后再进行添加操作;
	* 示例:
		* public void updateDocument() throws Exception{
		* //创建一个新的文档对象
		* Document document =new Document();
		* //向文档对象中添加域
		* document.add(new TextField("name","更新之后的文档",Field.Store.YES));
		* document.add(new TextField("name1","更新之后的文档1",Field.Store.YES));
		* document.add(new TextField("name2","更新之后的文档2",Field.Store.YES));
		* //更新索引库
		* indexWriter.updateDocument(new Term("name","spring"),document);
		* indexWriter.close();
		* }
6. 数值范围查询
	1. TermQuery:	
		1. 根据关键词查询,需要指定要查询的域及要查询的关键词;
		2. 范围进行查询
			
	2. 使用QueryPaser进行查询
		1. 可以对要查询的内容先进行分词,然后基于分词的结果进行查询;
		2. 需要导入jar包:lucene-queryparser-7.4.0.jar		

	3. 范围查询和QueryParser查询的代码整合如下:
		
		public class SearchIndex {
		    private IndexReader indexReader;
		    private IndexSearcher indexSearcher;
		    @Before
		    public void init() throws Exception {
		        indexReader = DirectoryReader.open(FSDirectory.open(new File("C:\\temp\\index").toPath()));
		        indexSearcher = new IndexSearcher(indexReader);
		    }
		
		    @Test
		    public void testRangeQuery() throws Exception {
		        //创建一个Query对象
		        Query query = LongPoint.newRangeQuery("size", 0l, 100l);
		        printResult(query);
		    }
		
		    private void printResult(Query query) throws Exception {
		        //执行查询
		        TopDocs topDocs = indexSearcher.search(query, 10);
		        System.out.println("总记录数:" + topDocs.totalHits);
		        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		        for (ScoreDoc doc:scoreDocs){
		            //取文档id
		            int docId = doc.doc;
		            //根据id取文档对象
		            Document document = indexSearcher.doc(docId);
		            System.out.println(document.get("name"));
		            System.out.println(document.get("path"));
		            System.out.println(document.get("size"));
		            //System.out.println(document.get("content"));
		            System.out.println("-----------------寂寞的分割线");
		        }
		        indexReader.close();
		    }
		
		    @Test
		    public void testQueryParser() throws Exception {
		        //创建一个QueryPaser对象,两个参数
		        QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
		        //参数1:默认搜索域,参数2:分析器对象
		        //使用QueryPaser对象创建一个Query对象
		        Query query = queryParser.parse("lucene是一个Java开发的全文检索工具包");
		        //执行查询
		        printResult(query);
		    }
		}