全文检索基础 Lucene

        Luncene是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,以此为基础在目标系统中建立起完整的全文检索引擎。

全文检索:将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。这种先建立索引,再对索引进行搜索的过程就叫全文检索。例如:字典。字典的拼音表和部首检字表就相当于字典的索引。

如何实现全文检索:

一、创建索引

索引和搜索流程图:                                                    

其中索引库中保存着两部分内容:索引文件对象

接下来以搜索d盘上文件的内容案例来演示索引和搜索过程:

1,获取原始文档:通过IO流获取d盘上有一些文件如图

2,创建文档对象

获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档中包括一个一个的域(Field),域中存储内容。document,Document中包括一些Field(file_name文件名称、file_path文件路径、file_size文件大小、file_content文件内容),如下图

注意:每个Document可以有多个Field,不同的Document可以有不同的Field,同一个Document可以有相同的Field(但这样去创建意义不大),每个文档都有一个唯一的编号,就是文档id。

3,分析文档

将原始内容创建为包含域(Field)的文档(document),需要再对域中的内容进行分析。

例如,原始文档内容为:Lucene is a Java full-text search engine.  Lucene is not a complete application, but rather a code library and API that can easily be used to add search capabilities to applications.

分析后得到的语汇单元(term):lucene、java、full、search、engine......

每个单词叫做一个Term,不同的域中拆分出来的相同的单词是不同的term。term中包含两部分一部分是文档的域名,另一部分是单词的内容。例如,文件名中包含apache和文件内容中包含的apache是不同的term:

Term K 域(文件名) V apache  Term K 域(文件内容) V apache      Term将作为索引 保存在索引库

4,创建索引  

对所有文档分析得出的语汇单元(Term)进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到Document(文档)。

二、查询索引

查询索引也是搜索的过程。搜索就是用户输入关键字,从索引(index)中进行搜索的过程。根据关键字搜索索引,根据索引找到对应的文档,从而找到要搜索的内容(这里指磁盘上的文件)。

1,用户查询接口

全文检索系统提供用户搜索的界面供用户提交搜索的关键字,搜索完成展示搜索结果。如:

2,创建查询

用户输入查询关键字执行搜索之前需要先构建一个查询对象,查询对象中可以指定查询要搜索的Field文档域、查询关键字等,查询对象会生成具体的查询语法。

例如:语法 “fileName:lucene”表示要搜索Field域的内容为“lucene”的文档

3,执行查询

搜索索引过程:根据查询语法在倒排索引词典表中分别找出对应搜索词的索引,从而找到索引所链接的文档链表。

例如:搜索语法为“fileName:lucene”表示搜索出fileName域中包含Lucene的文档。搜索过程就是在索引上查找域为fileName,并且关键字为Lucene的term,并根据term找到文档id列表。

4,渲染结果

以一个友好的界面将查询结果展示给用户,用户根据搜索结果找自己想要的信息,比如搜索结果中将关键字高亮显示,百度提供的快照等。

三、创建索引具体代码实现

第一步:创建一个indexwriter对象。

1)指定索引库的存放位置Directory对象

2)指定一个分析器,对文档内容进行分析。

第二步:创建document对象。

第三步:创建field对象,将field添加到document对象中。

第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。

第五步:关闭IndexWriter对象。

在写代码之前先介绍下Filed的属性:

是否分析是否对域的内容进行分词处理。前提是我们要对域的内容进行查询

是否索引将Field分析后的词或整个Field值进行索引,只有索引方可搜索到。比如:商品名称、商品简介分析后进行索引,订单号、身份证号不用分析但也要索引,这些将来都要作为查询条件。

是否存储将Field值存储在文档中,存储在文档中的Field才可以从Document中获取。比如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。

创建索引示例:

// 创建索引
	@Test
	public void testIndex() throws Exception {
		// 第一步:创建一个java工程,并导入jar包。
		// 第二步:创建一个indexwriter对象。
		Directory directory = FSDirectory.open(new File("D:\\temp\\index"));
		// Directory directory = new RAMDirectory();//保存索引到内存中 (内存索引库)
        //Analyzer analyzer = new StandardAnalyzer();// 官方推荐
		Analyzer analyzer = new IKAnalyzer();// 官方推荐
		IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
		IndexWriter indexWriter = new IndexWriter(directory, config);
		// 1)指定索引库的存放位置Directory对象
		// 2)指定一个分析器,对文档内容进行分析。
		// 第三步:创建field对象,将field添加到document对象中。
		File f = new File("D:\\Lucene&solr\\searchsource");
		File[] listFiles = f.listFiles();
		for (File file : listFiles) {
			// 第三步:创建document对象。
			Document document = new Document();
			// 文件名称
			String file_name = file.getName();
			Field fileNameField = new TextField("fileName", file_name, Store.YES);
			// 文件大小
			long file_size = FileUtils.sizeOf(file);
			Field fileSizeField = new LongField("fileSize", file_size, Store.YES);
			// 文件路径
			String file_path = file.getPath();
			Field filePathField = new StoredField("filePath", file_path);
			// 文件内容
			String file_content = FileUtils.readFileToString(file);
			Field fileContentField = new TextField("fileContent", file_content, Store.YES);

			document.add(fileNameField);
			document.add(fileSizeField);
			document.add(filePathField);
			document.add(fileContentField);
			// 第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
			indexWriter.addDocument(document);

		}
		// 第五步:关闭IndexWriter对象。
		indexWriter.close();
	}

四、查询索引具体代码实现

第一步:创建一个Directory对象,也就是索引库存放的位置。

第二步:创建一个indexReader对象,需要指定Directory对象。

第三步:创建一个indexsearcher对象,需要指定IndexReader对象

第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。

第五步:执行查询。

第六步:返回查询结果。遍历查询结果并输出。

第七步:关闭IndexReader对象

IndexSearcher搜索方法

@Test
	public void testSearch() throws Exception {
		// 第一步:创建一个Directory对象,也就是索引库存放的位置。
		Directory directory = FSDirectory.open(new File("D:\\temp\\index"));// 磁盘
		// 第二步:创建一个indexReader对象,需要指定Directory对象。
		IndexReader indexReader = DirectoryReader.open(directory);
		// 第三步:创建一个indexsearcher对象,需要指定IndexReader对象
		IndexSearcher indexSearcher = new IndexSearcher(indexReader);
		// 第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。
		Query query = new TermQuery(new Term("fileName", "lucene"));
		// 第五步:执行查询。
		TopDocs topDocs = indexSearcher.search(query, 10);
		// 第六步:返回查询结果(文档id)。遍历查询结果并输出。
		ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		for (ScoreDoc scoreDoc : scoreDocs) {
			int doc = scoreDoc.doc;
			Document document = indexSearcher.doc(doc);
			// 文件名称
			String fileName = document.get("fileName");
			System.out.println(fileName);
			// 文件内容
			String fileContent = document.get("fileContent");
			System.out.println(fileContent);
			// 文件大小
			String fileSize = document.get("fileSize");
			System.out.println(fileSize);
			// 文件路径
			String filePath = document.get("filePath");
			System.out.println(filePath);
			System.out.println("------------");
		}
		// 第七步:关闭IndexReader对象
		indexReader.close();

	}

索引库的维护:添加索引、删除索引、修改索引、查询索引

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值