黑马程序员技术交流社区

标题: 【太原校区】关于Lucene技术介绍和使用整理 [打印本页]

作者: 王高飞    时间: 2018-12-5 09:45
标题: 【太原校区】关于Lucene技术介绍和使用整理
本帖最后由 王高飞 于 2018-12-5 13:37 编辑

Lucene&solr:维护数据,实现全文检索的
                        Lucene:solr底层
                        solr:服务器
一 什么是全文检索
  数据分类:
                        结构化数据:有固定格式(数据类型)和有限的长度 比如:数据库表中的数据 元数据:关于数据的数据
                                                查询: 使用SQL语句查询结构化数据  速度快
                                                数据量大时 在数据库给某字段创建索引 但是索引不支持like(模糊)查询
                                                只能做等值查询
                                                解决模糊查询的问题 需要创建另外一套索引库:使用分词器
                                                
                        非结构化数据:没有固定格式(数据类型)也没有有限的长度 比如:word ppt excel pdf txt等磁盘上的文件
                                                查询: 1 目测 顺序扫描 挨个硬找 比较慢
                                                          2 IO读取
                                                          3 全文检索:
                                                                        
        全文检索:
                        对源数据创建索引+在索引上查询   电商项目
                索引:
                        将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,
                        然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
                        这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
                        
                        

二 全文检索的应用场景
    1 搜索引擎: 谷歌 百度 搜狗 360
        2 站内搜索: 淘宝 京东 微博 论坛
          全文检索的数据不是直接来自数据库 而是来自通过数据库数据创建的索引库


三 怎么实现全文检索
        使用Lucene实现
        
四 Lucene的简介
        Lucene是apache下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。
        Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
        目前我们使用核心core和分词器两个jar

五 Lucene实现全文检索的流程
        1 创建索引
           0 确定源文档:
                        要创建索引 使用全文检索的文件
           1 获取源文档:
             源文档是什么?
                        场景1:搜索引擎:指的是互联网上的所有网页
                        场景2:站内搜索:
                                        1 磁盘上的文件
                                        2 数据库表中的数据
                 获取源文档方式:
                          1 搜索引擎
                                        使用网络爬虫(网络机器人)得到的 爬虫访问互联网上的每一个网页,将获取到的网页内容存储起来。
                          2 站内搜索:
                                        1 磁盘上的文件:IO流
                                        2 数据库表中的数据:sql查询
           2 构建文档对象document
             每个document中的属性可以不同 每个document都需要有唯一的id
                 一个Document对象放的内容是:
                                一个网页的内容(网络地址URL 网页标题 网页内容)
                                一个文件中内容(文件名 地址 大小 内容等)  
                                表中的一条数据(一条数据每个列的内容 有多少列就应该创建多少个域)
           3 分析文档,对内容分词
                 使用原始的分词
                 文件spring.txt内容:The Spring Framework provides a comprehensive programming and configuration model.
                 分词:为了创建索引库
                                                        1 按空格分词:按空格把语句划分成单词
                                                        2 处理大小写:忽略单词的大小写
                                                        3 处理停用词:去除停用词
                                                        4 标点符号:去除标点符号
                 分词后:
                        name:spring
                        content:spring
                        content:framework
                        content:provides
                        content:comprehensive
                        content:programming
                        content:configuration
                        content:model
                                                
           4 创建索引(存储索引到索引库)
                        
                        1 一个文档document可以有多个域 不同的文档可以有不同的域 同一个Document可以有相同的Field(域名和域值都相同)
                        2 域Field:域名+域值
                          域名    Filename
                                          Content
                                          size
                                          path
                          域值 spring mvc l love you
                        3 term:不同的域中拆分出来的相同的单词是不同的term
                                    域名+单词内容 Filename:spring
                                                                  Content:love
                                                                  Content:provides
                                                                  Content:spring
                        4 对所有文档分析得出的语汇单元term进行索引
                          索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到Document(文档)。
                          
                        5 创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构。
                              倒排索引使得每个关键字索引对应多个文档ID,通过索引找到文档。
                        
                          传统方法是正排索引,根据文档去搜索关键词,根据文件找到该文件的内容,在文件内容中匹配搜索关键字,这种方法是顺序扫描方法,数据量大、搜索慢。
        2 查询索引:
                查询索引也是搜索的过程。搜索就是用户输入关键字,从索引(index)中进行搜索的过程。
                根据关键字搜索索引,根据索引找到对应的文档,从而找到要搜索的内容
        
                1 用户查询接口 输入查询关键字的位置
                2 创建查询
                3 执行查询
                4 渲染结果

六 Lucene入门案例
    1 导入jar :lucene-core-4.10.3.jar、lucene-analyzers-common-4.10.3.jar  commons-io.jar(读写本地文件)
        2 创建索引:
                第一步:创建一个java工程,并导入jar包。
                第二步:创建一个indexwriter对象。
                                1 指定索引库的存放位置Directory对象
                                2 指定一个分析器Analyzer,对文档内容进行分析。
                第二步:创建document对象。
                第三步:创建field对象,设置域名 域值 是否分析 将field添加到document对象中。
                第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
                第五步:关闭IndexWriter对象。
                源码:
                        //指定索引存放位置
                        Directory directory=FSDirectory.open(new File("D:\Everday\Lucene&solr\Lucene&solr-day01\资料\index"));
                        //创建一个标准分析库 分词器
                        Analyzer analyzer=new StandardAnalyzer();
                        //        //创建indexwriterCofig对象
                        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST, analyzer);
                        ////创建indexwriter对象
                        IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
                        //原文档
                        File dir = new File("D:\Everday\Lucene&solr\Lucene&solr-day01\资料\上课用的查询资料searchsource");
                        //获得文件夹内的所有文件
                        File[] listFiles = dir.listFiles();
                        for (File f : listFiles) {
                                //文件名
                                String fileName = f.getName();
                                //文件内容
                                String fileContent = FileUtils.readFileToString(f);
                                //文件路径
                                String filePath = f.getPath();
                                //文件的大小
                                long fileSize  = FileUtils.sizeOf(f);
                                //创建文件名域
                                //第一个参数:域的名称
                                //第二个参数:域的内容
                                //第三个参数:是否分析 索引 存储
                                Field fileNameField = new TextField("filename", fileName, Store.YES);
                                //文件内容域
                                Field fileContentField = new TextField("content", fileContent, Store.YES);
                                //文件路径域
                                Field filePathField = new StoredField("path", filePath);
                                //文件大小域
                                Field fileSizeField = new LongField("size", fileSize, Store.YES);
                                
                                //创建document对象
                                Document document = new Document();
                                document.add(fileNameField);
                                document.add(fileContentField);
                                document.add(filePathField);
                                document.add(fileSizeField);
                                //创建索引,并写入索引库
                                indexWriter.addDocument(document);
                        }
                        
                        //释放资源
                        indexWriter.close();
                }
               
                使用luke工具查看索引文件,运行bat文件 打开软件
               
        2 查询索引
                第一步:创建一个Directory对象,指定索引库存放的位置。
                第二步:创建一个indexReader对象,需要指定Directory对象。
                第三步:创建一个indexsearcher对象,需要指定IndexReader对象
                第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。
                第五步:执行查询方法。
                                query:指定条件
                            n:查询数据量的限制
                第六步:返回查询结果TopDocs。遍历查询结果并输出。
                                TopDocs:提供了获得结果的属性
                                  topDocs.totalHits:匹配搜索条件的总记录数
                                  topDocs.scoreDocs:顶部匹配记录
                第七步:关闭IndexReader对象
                源码:
                            //指定索引库存放的路径
                                Directory directory = FSDirectory.open(new File("D:\Everday\Lucene&solr\Lucene&solr-day01\资料\index"));
                                //创建indexReader对象
                                IndexReader indexReader = DirectoryReader.open(directory);
                                //创建indexsearcher对象
                                IndexSearcher indexSearcher = new IndexSearcher(indexReader);
                                //创建查询
                                Query query = new TermQuery(new Term("filename", "spring"));
                                //执行查询
                                //第一个参数是查询对象,第二个参数是查询结果返回的最大值
                                TopDocs topDocs = indexSearcher.search(query, 100);
                                //查询结果的总条数
                                System.out.println("查询结果的总条数:"+ topDocs.totalHits);
                                //遍历查询结果
                                //topDocs.scoreDocs存储了document对象的id
                                for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
                                        //scoreDoc.doc属性就是document对象的id
                                        //根据document的id找到document对象
                                        Document document = indexSearcher.doc(scoreDoc.doc);
                                        System.out.println(document.get("filename"));
                                        System.out.println(document.get("content"));
                                        System.out.println(document.get("path"));
                                        System.out.println(document.get("size"));
                                        System.out.println("------------------------------------");
                                }
                                //关闭indexreader对象
                                indexReader.close();
                        }               
                        
八 分词器 分词器
        apache自带的:中文分析效果不好
                1 StandardAnalyzer:
                        单字分词:就是按照中文一个字一个字地进行分词。如:“我爱中国”,
                        效果:“我”、“爱”、“中”、“国”。
                2 CJKAnalyzer
                        按两个字进行切分。如:“我是中国人”,效果:“我是”、“是中”、“中国”“国人”。
                3 SmartChineseAnalyzer
                        导包 lucene-analyzers-smartcn-4.10.3.jar
                        对中文支持较好,但扩展性差,扩展词库,禁用词库和同义词库等不好处理
        第三方提供的: 支持中文分析效果好
                IKAnalyzer :
                导入jar:IKAnalyzer2012FF_u1.jar
                配置两个配置文件:stopword.dic和ext.dic 对中文分词效果较好 也可以自己指定禁用词和扩展词
九 分词器Analyzer的使用时机
                1 创建索引时使用Analyzer
                        对于一些域值不需要分析器
                        1 不作为查询条件的内容,比如文件路径
                        2 不是匹配内容中的词而匹配Field的整体内容,比如订单号、身份证号等。
                2 查询时也需要分词
        注意:搜索使用的分析器要和索引使用的分析器一致。        
        
               
               
作者: Julien27    时间: 2018-12-5 12:14
学习了,感谢大神详细的总结
作者: liuchengwei1    时间: 2018-12-5 12:18

作者: Vicky韦    时间: 2018-12-5 12:35

作者: liudongjie    时间: 2018-12-5 12:51
厉害厉害厉害
作者: liudongjie    时间: 2018-12-5 12:55
啦啦啦
作者: 张兆秋    时间: 2018-12-5 14:36
66666
作者: HFFFX    时间: 2018-12-5 14:50
赞赞赞
作者: 郝永亮    时间: 2018-12-5 15:06

作者: miaohangbo    时间: 2018-12-5 15:25

作者: cuichang1    时间: 2018-12-5 16:11

作者: liuchengwei1    时间: 2018-12-6 14:15
很详细!
作者: liudongjie    时间: 2018-12-6 17:14
很详细!
作者: renhua    时间: 2018-12-6 21:01

作者: 郝永亮    时间: 2018-12-19 13:36
优秀
作者: 赵国旺    时间: 2019-1-16 11:05
大神
作者: 吕小布735    时间: 2019-1-17 08:55
很金典  666不错不错




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2