全文检索技术(一):Lucene入门

Opal ·
更新时间:2024-11-10
· 978 次阅读

一、全文检索的简介

1、全文检索的介绍

1.1、数据分类

结构化数据:格式固定、长度固定、数据类型固定,如:数据库数据。 非结构化数据:格式不固定、长度不固定、数据类型不固定,如:word文档、pdf文档、邮件、html、txt等。

1.2、数据的查询

结构化数据的查询:SQL语句,查询结构化数据的方法。简单、速度快。 非结构化数据的查询:需要先把非结构化数据转化为结构化数据,并创建索引,然后查询索引找到对应的数据。 索引:一个为了提高查询速度,创建某种数据结构的集合。

1.3、全文检索

先创建索引然后查询索引的过程叫做全文索引。 索引一次创建可以多次使用,表现为每次查询速度很快。

2、Lucene引入

Lucene是一个基于java开发全文检索工具包。 二、Lucene全文检索的流程

1、创建索引

1.1、获取文档:

 原始文档:要基于那些数据进行搜索,那么这些数据就是原始文档。 搜索引擎:使用爬虫获取原始文档 站内搜索:数据库中的数据 案例:直接使用io流读取磁盘上的文件。

1.2、构建文档对象

对应每个原始文档创建一个Document对象,每个document对象中包含多个域(Field),域中保存就是原始文档数据

1.3、分析文档

根据空格进行字符串拆分,得到一个单词列表; 把单词统一转换成小写; 去除标点符号,去除停用词(无意义的词)。 每个关键词都封装成一个Term对象中,Term中包含两部分内容:关键词所在的域和关键词本身。

注意:不同的域中拆分出来的相同的关键词是不同的Term

1.4、创建索引

基于关键词列表创建一个索引,保存到索引库中; 索引库中:索引、document对象和关键词与文档的对应关系。 通过词语找到文档,这种索引的结构叫做倒排索引结构

2、查询索引

用户查询接口:用户输入查询条件地方。 把关键词封装成一个查询对象:要查询的域和要搜索的关键词。 执行查询:根据要查询的关键词到对应的域上进行搜索,找到关键词,根据关键词找到对应的文档。 渲染结果:根据文档的id找到文档对象,根据文档的id找到文档对象,分页处理,最终展示给用户看。 三、Lucene入门程序

1、搭建环境

创建一个maven工程,导入依赖

org.apache.lucene lucene-core 7.4.0 org.apache.lucene lucene-analyzers-common 7.4.0 commons-io commons-io 2.6 junit junit 4.12

注意:保证jdk在1.8以上。 

2、创建索引

/** * 创建索引 * * @throws Exception */ @Test public void createIndex() throws Exception { //1、创建一个Director对象,指定索引库保存的位置。 Directory directory = FSDirectory.open(new File("E:\\Resources\\temp\\index").toPath()); //2、基于Directory对象创建一个IndexWriter对象 IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig()); //3、读取磁盘上的文件,对应每个文件创建一个文档对象。 File dir = new File("E:\\Resources\\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(); //4、向文档对象中添加域 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(); }

3、查询索引

/** * 查询索引 * * @throws Exception */ @Test public void searchIndex() throws Exception { //1、创建一个Director对象,指定索引库的位置 Directory directory = FSDirectory.open(new File("E:\\Resources\\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、分析器的分词效果

如果需要使用中文分词器,需要导入IK分词器的jar包

/** * 分析器的分词效果 * * @throws Exception */ @Test public void testTokenStream() throws Exception { //1、创建一个Analyzer对象,StandardAnalyzer对象 //Analyzer analyzer = new StandardAnalyzer();//标准分词对象 Analyzer analyzer = new IKAnalyzer();//扩展中文分词对象 //2、使用分析器对象的tokenStream方法获得一个TokenStream对象 TokenStream tokenStream = analyzer.tokenStream("test", "输入用户和密码检出svn服务器上的项目"); //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、使用Luke工具查看索引文件


作者:启帆远航



lucene 全文检索

需要 登录 后方可回复, 如果你还没有账号请 注册新账号