lucene_lucene初体验 - CSDN
lucene 订阅
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。 [1] 展开全文
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。 [1]
信息
外文名
Lucene
类    属
搜索引擎
开发时间
2000年
中文名
全文搜索引擎
开发人
Doug Cutting
Lucene历史
Lucene最初是由Doug Cutting开发的,在SourceForge的网站上提供下 Lucene 图片(2张) 载。在2001年9月作为高质量的开源Java产品加入到Apache软件基金会的 Jakarta家族中。随着每个版本的发布,这个项目得到明显的增强,也吸引了更多的用户和开发人员。2004年7月,Lucene1.4版正式发布,10月的1.4.2版本做了一次bug修正。表1.1显示了Lucene的发布历史。版本 发布日期 里程碑0.01 2000年3月 第一个开源版本(SourceForge)1.0 2000年10月1.01b 2001年7月 最后的SourceForge版本1.2 2002年6月 第一个Apache Jakarta版本1.3 2003年12月 复合索引格式,查询分析器增加,远程搜索,token定位,可扩展的API1.4 2004年7月 Sorting, span queries, term vectors1.4.1 2004年8月 排序性能的bug修正1.4.2 2004年10月 IndexSearcher optimization and misc. fixes1.4.3 2004年冬 Misc. fixes2.4.1 2009年3月8日发布新版本2.3.0 2008年1月 更新为2.3.02.4.0 2008年10月 更新为2.4.02.4.1 2009年 5月 更新为 2.4.12.9.0 2009年9月25号 更新为2.9.02.9.1 2009年11月6号 更新为2.9.13.0.0 2009年11月25号 更新为3.0.03.0.1 2010年2月26号 更新为3.0.13.0.2 2010年6月18号 更新为3.0.23.0.3 2010年12月3号 更新为3.0.33.3.0 2011年7月初 更新为3.3.03.4.0 2011年9月14日 更新为3.4.03.5.0 2011年11月26日 更新为3.5.03.6.0 2012年4月12日更新为3.6.03.6.1 2012年7月23日更新为3.6.14.0 2012年10月12日更新为4.0 [2]  4.2 2013年3月11日更新为4.24.3.1 2013-06-18发布4.4 2013年7月23日更新到4.44.5 2013年10月5日更新到4.55.0.0 2015年2月20日更新到5.0.0
收起全文
精华内容
参与话题
  • Lucene介绍与使用

    万次阅读 多人点赞 2019-11-01 10:18:15
    1、了解搜索技术 1.1 什么是搜索 简单的说,搜索就是搜寻、查找,在IT行业中就是指用户输入关键字,通过相应的算法,查询并返回用户所需要的信息。 1.2 普通的数据库搜索 类似:select * from 表名 where 字段名...

    1、了解搜索技术

    1.1 什么是搜索

    简单的说,搜索就是搜寻、查找,在IT行业中就是指用户输入关键字,通过相应的算法,查询并返回用户所需要的信息。

    1.2 普通的数据库搜索

    类似:select * from 表名 where 字段名 like ‘%关键字%’

    例如:select * from article where content like ’%here%’

    结果: where here shere

    1.3 新的业务需求

    比如,用户在百度文本框中输入,“吃饭睡觉写程序”,会出现的以下结果:

    在这里插入图片描述

    从结果可以看出,百度搜索具备以下明显特点:

    1、即使在相关结果数量接近500万时,也能快速得出结果。

    2、搜索的结果不仅仅局限于完整的“吃饭睡觉写程序”这一短语,而是将此短语拆分成,“写程序”,“吃饭”,“睡觉”,“程序”等关键字。

    3、对拆分后的搜索关键字进行标红显示。

    4、…

    问题:上述功能,使用大家以前学过的数据库搜索能够方便实现吗?

    1.4 普通的数据库搜索的缺陷

    类似:select * from 表名 where 字段名 like ‘%关键字%’

    例如:select * from article where content like ’%here%’

    结果: where here shere

    1、因为没有通过高效的索引方式,所以查询的速度在大量数据的情况下是很慢。

    2、搜索效果比较差,只能对用户输入的完整关键字首尾位进行模糊匹配。用户搜索的结果误多输入一个字符,可能就导致查询出的结果远离用户的预期。

    2、 搜索技术

    2.1 搜索引擎的种类

    搜索引擎按照功能通常分为垂直搜索和综合搜索。

    1、垂直搜索是指专门针对某一类信息进行搜索。例如:会搜网 主要做商务搜索的,并且提供商务信息。除此之外还有爱看图标网、职友集等。
    
    2、综合搜索是指对众多信息进行综合性的搜索。例如:百度、谷歌、搜狗、360搜索等。 
    

    2.2 倒排索引

    倒排索引又叫反向索引(右下图)以字或词为文档中出现的位置情况。

    在这里插入图片描述

    在实际的运用中,我们可以对数据库中原始的数据结构(左图),在业务空闲时事先根据左图内容,创建新的倒排索引结构的数据区域(右图)。

    用户有查询需求时,先访问倒排索引数据区域(右图),得出文档id后,通过文档id即可快速,准确的通过左图找到具体的文档内容。

    这一过程,可以通过我们自己写程序来实现,也可以借用已经抽象出来的通用开源技术来实现。


    4 Lucene概述

    4.1 什么是Lucene

    LOGO:

    在这里插入图片描述

    • Lucene是一套用于全文检索和搜寻的开源程序库,由Apache软件基金会支持和提供

    • Lucene提供了一个简单却强大的应用程序接口(API),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具

    • Lucene并不是现成的搜索引擎产品,但可以用来制作搜索引擎产品

    • 官网:http://lucene.apache.org/

    4.2 什么是全文检索?

    在这里插入图片描述

    4.3 Lucene下载及版本问题

    官网:

    在这里插入图片描述

    • 目前最新的版本是7.x系列,但是在企业中还是用4.x比较多,所以我们学习4.x的版本

    老版本下载地址:

    http://archive.apache.org/dist/lucene/java/

    4.4 Lucene、Solr、Elasticsearch关系

    Lucene:底层的API,工具包

    Solr:基于Lucene开发的企业级的搜索引擎产品

    Elasticsearch:基于Lucene开发的企业级的搜索引擎产品

    5 Lucene的基本使用

    使用Lucene的API来实现对索引的增(创建索引)、删(删除索引)、改(修改索引)、查(搜索数据)。

    5.1 创建索引

    5.1.1 创建索引的流程

    在这里插入图片描述

    文档Document:数据库中一条具体的记录

    字段Field:数据库中的每个字段

    目录对象Directory:物理存储位置

    写出器的配置对象:需要分词器和lucene的版本

    5.1.2 添加依赖 在这里插入图片描述

    <properties>
        <lunece.version>4.10.2</lunece.version>
    
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- lucene核心库 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>${lunece.version}</version>
        </dependency>
        <!-- Lucene的查询解析器 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>${lunece.version}</version>
        </dependency>
        <!-- lucene的默认分词器库 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>${lunece.version}</version>
        </dependency>
        <!-- lucene的高亮显示 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-highlighter</artifactId>
            <version>${lunece.version}</version>
        </dependency>
    </dependencies>
    

    5.1.3 代码实现

    步骤:

    //1 创建文档对象
    //2 创建存储目录
    //3 创建分词器
    //4 创建索引写入器的配置对象
    //5 创建索引写入器对象
    //6 将文档交给索引写入器
    //7 提交
    //8 关闭
    
     // 创建索引
        @Test
        public void testCreate() throws Exception{
            //1 创建文档对象
            Document document = new Document();
            // 创建并添加字段信息。参数:字段的名称、字段的值、是否存储,这里选Store.YES代表存储到文档列表。Store.NO代表不存储
            document.add(new StringField("id", "1", Field.Store.YES));
            // 这里我们title字段需要用TextField,即创建索引又会被分词。StringField会创建索引,但是不会被分词
            document.add(new TextField("title", "谷歌地图之父跳槽facebook", Field.Store.YES));
    
            //2 索引目录类,指定索引在硬盘中的位置
            Directory directory = FSDirectory.open(new File("d:\\indexDir"));
            //3 创建分词器对象
            Analyzer analyzer = new StandardAnalyzer();
            //4 索引写出工具的配置对象
            IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);
            //5 创建索引的写出工具类。参数:索引的目录和配置信息
            IndexWriter indexWriter = new IndexWriter(directory, conf);
    
            //6 把文档交给IndexWriter
            indexWriter.addDocument(document);
            //7 提交
            indexWriter.commit();
            //8 关闭
            indexWriter.close();
     }
    

    在这里插入图片描述

    5.1.4 使用工具查看索引

    在这里插入图片描述

    5.1.5 创建索引的API详解

    5.1.5.1 Document(文档类)

    Document:文档对象,是一条原始的数据

    在这里插入图片描述

    5.1.5.2 Field(字段类)

    一个Document中可以有很多个不同的字段,每一个字段都是一个Field类的对象。

    一个Document中的字段其类型是不确定的,因此Field类就提供了各种不同的子类,来对应这些不同类型的字段。

    在这里插入图片描述

    这些子类有一些不同的特性:

    1)DoubleField、FloatField、IntField、LongField、StringField、TextField这些子类一定会被创建索引,但是不会被分词,而且不一定会被存储到文档列表。要通过构造函数中的参数Store来指定:如果Store.YES代表存储,Store.NO代表不存储

    在这里插入图片描述

    2)TextField即创建索引,又会被分词。StringField会创建索引,但是不会被分词。

    如果不分词,会造成整个字段作为一个词条,除非用户完全匹配,否则搜索不到:
    在这里插入图片描述
    我们一般,需要搜索的字段,都会做分词:

    在这里插入图片描述

    3)StoreField一定会被存储,但是一定不创建索引

    StoredField可以创建各种数据类型的字段:

    在这里插入图片描述

    在这里插入图片描述

    问题1:如何确定一个字段是否需要存储?

    如果一个字段要显示到最终的结果中,那么一定要存储,否则就不存储
    

    问题2:如何确定一个字段是否需要创建索引?

    如果要根据这个字段进行搜索,那么这个字段就必须创建索引。
    

    问题3:如何确定一个字段是否需要分词?

    前提是这个字段首先要创建索引。然后如果这个字段的值是不可分割的,那么就不需要分词。例如:ID
    

    5.1.5.3 Directory(目录类)

    指定索引要存储的位置

    在这里插入图片描述

    FSDirectory:文件系统目录,会把索引库指向本地磁盘。

    特点:速度略慢,但是比较安全
    

    RAMDirectory:内存目录,会把索引库保存在内存。

    特点:速度快,但是不安全
    

    5.1.5.4 Analyzer(分词器类)

    • 提供分词算法,可以把文档中的数据按照算法分词

    在这里插入图片描述

    这些分词器,并没有合适的中文分词器,因此一般我们会用第三方提供的分词器:

    在这里插入图片描述
    一般我们用IK分词器。

    5.1.5.5 IK分词器(重要)

    • 概述

    在这里插入图片描述

    林良益

    IK分词器官方版本是不支持Lucene4.X的,有人基于IK的源码做了改造,支持了Lucene4.X:

    在这里插入图片描述

    • 基本使用

    引入IK分词器:

    在这里插入图片描述

        <dependency>
        
          <groupId>com.janeluo</groupId>
        
          <artifactId>ikanalyzer</artifactId>
        
          <version>2012_u6</version>
        
        </dependency>
    

    在这里插入图片描述

    中文分词更专业:

    在这里插入图片描述

    • 扩展词典和停用词典

    IK分词器的词库有限,新增加的词条可以通过配置文件添加到IK的词库中,也可以把一些不用的词条去除:
    在这里插入图片描述
    [外链图片转存失败(img-f41wpopO-1562576510318)(assets/wps18CD.tmp.jpg)]

    扩展词典:用来引入一些自定义的新词
    停止词典:用来停用一些不必要的词条

    在这里插入图片描述

    结果:分词中,加入了我们新的词,被停用的词语没有被分词:

    在这里插入图片描述

    5.1.5.6 IndexWriterConfig(索引写出器配置类)

    1) 设置配置信息:Lucene的版本和分词器类型

    在这里插入图片描述

    2)设置是否清空索引库中的数据

    在这里插入图片描述

    5.1.5.7 IndexWriter(索引写出器类)

    • 索引写出工具,作用就是 实现对索引的增(创建索引)、删(删除索引)、改(修改索引)

    在这里插入图片描述

    • 可以一次创建一个,也可以批量创建索引
    // 批量创建索引
        @Test
        public void testCreate2() throws Exception{
            // 创建文档的集合
            Collection<Document> docs = new ArrayList<>();
            // 创建文档对象
            Document document1 = new Document();
            document1.add(new StringField("id", "1", Field.Store.YES));
            document1.add(new TextField("title", "谷歌地图之父跳槽facebook", Field.Store.YES));
            docs.add(document1);
            // 创建文档对象
            Document document2 = new Document();
            document2.add(new StringField("id", "2", Field.Store.YES));
            document2.add(new TextField("title", "谷歌地图之父加盟FaceBook", Field.Store.YES));
            docs.add(document2);
            // 创建文档对象
            Document document3 = new Document();
            document3.add(new StringField("id", "3", Field.Store.YES));
            document3.add(new TextField("title", "谷歌地图创始人拉斯离开谷歌加盟Facebook", Field.Store.YES));
            docs.add(document3);
            // 创建文档对象
            Document document4 = new Document();
            document4.add(new StringField("id", "4", Field.Store.YES));
            document4.add(new TextField("title", "谷歌地图之父跳槽Facebook与Wave项目取消有关", Field.Store.YES));
            docs.add(document4);
            // 创建文档对象
            Document document5 = new Document();
            document5.add(new StringField("id", "5", Field.Store.YES));
            document5.add(new TextField("title", "谷歌地图之父拉斯加盟社交网站Facebook", Field.Store.YES));
            docs.add(document5);
    
            // 索引目录类,指定索引在硬盘中的位置
            Directory directory = FSDirectory.open(new File("d:\\indexDir"));
            // 引入IK分词器
            Analyzer analyzer = new IKAnalyzer();
            // 索引写出工具的配置对象
            IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);
            // 设置打开方式:OpenMode.APPEND 会在索引库的基础上追加新索引。OpenMode.CREATE会先清空原来数据,再提交新的索引
            conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
    
            // 创建索引的写出工具类。参数:索引的目录和配置信息
            IndexWriter indexWriter = new IndexWriter(directory, conf);
            // 把文档集合交给IndexWriter
            indexWriter.addDocuments(docs);
            // 提交
            indexWriter.commit();
            // 关闭
            indexWriter.close();
        }
    

    5.2 查询索引数据

    5.2.1 代码实现

    实现步骤:

    //1 创建读取目录对象
    
    //2 创建索引读取工具
    
    //3 创建索引搜索工具
    
    //4 创建查询解析器
    
    //5 创建查询对象
    
    //6 搜索数据
    
    //7 各种操作
    
    
    @Test
        public void testSearch() throws Exception {
            // 索引目录对象
            Directory directory = FSDirectory.open(new File("d:\\indexDir"));
            // 索引读取工具
            IndexReader reader = DirectoryReader.open(directory);
            // 索引搜索工具
            IndexSearcher searcher = new IndexSearcher(reader);
    
            // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器
            QueryParser parser = new QueryParser("title", new IKAnalyzer());
            // 创建查询对象
            Query query = parser.parse("谷歌");
    
            // 搜索数据,两个参数:查询条件对象要查询的最大结果条数
            // 返回的结果是 按照匹配度排名得分前N名的文档信息(包含查询到的总条数信息、所有符合条件的文档的编号信息)。
            TopDocs topDocs = searcher.search(query, 10);
            // 获取总条数
            System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");
            // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (ScoreDoc scoreDoc : scoreDocs) {
                // 取出文档编号
                int docID = scoreDoc.doc;
                // 根据编号去找文档
                Document doc = reader.document(docID);
                System.out.println("id: " + doc.get("id"));
                System.out.println("title: " + doc.get("title"));
                // 取出文档得分
                System.out.println("得分: " + scoreDoc.score);
            }
        }
    
    

    5.2.2 核心API

    5.2.2.1 QueryParser(查询解析器)

    1)QueryParser(单一字段的查询解析器)

    在这里插入图片描述

    2)MultiFieldQueryParser(多字段的查询解析器)

    在这里插入图片描述

    5.2.2.2 Query(查询对象,包含要查询的关键词信息)

    • 1)通过QueryParser解析关键字,得到查询对象

    在这里插入图片描述

    • 2)自定义查询对象(高级查询)

    我们可以通过Query的子类,直接创建查询对象,实现高级查询(后面详细讲)

    在这里插入图片描述

    5.2.2.3 IndexSearch(索引搜索对象,执行搜索功能)

    IndexSearch可以帮助我们实现:快速搜索、排序、打分等功能。

    IndexSearch需要依赖IndexReader类

    在这里插入图片描述

    查询后得到的结果,就是打分排序后的前N名结果。N可以通过第2个参数来指定:

    在这里插入图片描述

    5.2.2.4 TopDocs(查询结果对象)

    通过IndexSearcher对象,我们可以搜索,获取结果:TopDocs对象

    在TopDocs中,包含两部分信息:

    int totalHits :查询到的总条数
    
    ScoreDoc[] scoreDocs	: 得分文档对象的数组
    

    在这里插入图片描述

    5.2.2.5 ScoreDoc(得分文档对象)

    ScoreDoc是得分文档对象,包含两部分数据:

    int doc	:文档的编号----lucene给文档的一个唯一编号
    
    float score	:文档的得分信息
    
    拿到编号后,我们还需要根据编号来获取真正的文档信息
    

    在这里插入图片描述

    5.2. 特殊查询

    抽取公用的搜索方法:

    public void search(Query query) throws Exception {
            // 索引目录对象
            Directory directory = FSDirectory.open(new File("indexDir"));
            // 索引读取工具
            IndexReader reader = DirectoryReader.open(directory);
            // 索引搜索工具
            IndexSearcher searcher = new IndexSearcher(reader);
    
            // 搜索数据,两个参数:查询条件对象要查询的最大结果条数
            // 返回的结果是 按照匹配度排名得分前N名的文档信息(包含查询到的总条数信息、所有符合条件的文档的编号信息)。
            TopDocs topDocs = searcher.search(query, 10);
            // 获取总条数
            System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");
            // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    
            for (ScoreDoc scoreDoc : scoreDocs) {
                // 取出文档编号
                int docID = scoreDoc.doc;
                // 根据编号去找文档
                Document doc = reader.document(docID);
                System.out.println("id: " + doc.get("id"));
                System.out.println("title: " + doc.get("title"));
                // 取出文档得分
                System.out.println("得分: " + scoreDoc.score);
            }
        }
    

    5.2.3.1 TermQuery(词条查询)

    /*
         * 测试普通词条查询
         * 注意:Term(词条)是搜索的最小单位,不可再分词。值必须是字符串!
         */
        @Test
        public void testTermQuery() throws Exception {
            // 创建词条查询对象
            Query query = new TermQuery(new Term("title", "谷歌地图"));
            search(query);
        }
    

    在这里插入图片描述

    5.2.3.2 WildcardQuery(通配符查询)

     /*
         * 测试通配符查询
         * 	? 可以代表任意一个字符
         * 	* 可以任意多个任意字符
         */
        @Test
        public void testWildCardQuery() throws Exception {
            // 创建查询对象
            Query query = new WildcardQuery(new Term("title", "*歌*"));
            search(query);
        }
    

    5.2.3.3 FuzzyQuery(模糊查询)

     /*
         * 测试模糊查询
         */
        @Test
        public void testFuzzyQuery() throws Exception {
            // 创建模糊查询对象:允许用户输错。但是要求错误的最大编辑距离不能超过2
            // 编辑距离:一个单词到另一个单词最少要修改的次数 facebool --> facebook 需要编辑1次,编辑距离就是1
    //    Query query = new FuzzyQuery(new Term("title","fscevool"));
            // 可以手动指定编辑距离,但是参数必须在0~2之间
            Query query = new FuzzyQuery(new Term("title","facevool"),1);
            search(query);
        }
    

    5.2.3.4 NumericRangeQuery(数值范围查询)

    /*
    	 * 测试:数值范围查询
    	 * 注意:数值范围查询,可以用来对非String类型的ID进行精确的查找
    	 */
    	@Test
    	public void testNumericRangeQuery() throws Exception{
    		// 数值范围查询对象,参数:字段名称,最小值、最大值、是否包含最小值、是否包含最大值
    		Query query = NumericRangeQuery.newLongRange("id", 2L, 2L, true, true);
    		
    		search(query);
    	}
    

    5.2.3.5 BooleanQuery(组合查询)

     /*
         * 布尔查询:
         * 	布尔查询本身没有查询条件,可以把其它查询通过逻辑运算进行组合!
         * 交集:Occur.MUST + Occur.MUST
         * 并集:Occur.SHOULD + Occur.SHOULD
         * 非:Occur.MUST_NOT
         */
        @Test
        public void testBooleanQuery() throws Exception{
    
            Query query1 = NumericRangeQuery.newLongRange("id", 1L, 3L, true, true);
            Query query2 = NumericRangeQuery.newLongRange("id", 2L, 4L, true, true);
            // 创建布尔查询的对象
            BooleanQuery query = new BooleanQuery();
            // 组合其它查询
            query.add(query1, BooleanClause.Occur.MUST_NOT);
            query.add(query2, BooleanClause.Occur.SHOULD);
    
            search(query);
        }
    

    5.4 修改索引

    步骤:

    //1 创建文档存储目录

    	//2 创建索引写入器配置对象
    
    	//3 创建索引写入器
    
    	//4 创建文档数据
    
    	//5 修改
    
    	//6 提交
    
    	//7 关闭
    
    /* 测试:修改索引
         * 注意:
         * 	A:Lucene修改功能底层会先删除,再把新的文档添加。
         * 	B:修改功能会根据Term进行匹配,所有匹配到的都会被删除。这样不好
         * 	C:因此,一般我们修改时,都会根据一个唯一不重复字段进行匹配修改。例如ID
         * 	D:但是词条搜索,要求ID必须是字符串。如果不是,这个方法就不能用。
         * 如果ID是数值类型,我们不能直接去修改。可以先手动删除deleteDocuments(数值范围查询锁定ID),再添加。
         */
    @Test
    public void testUpdate() throws Exception{
        // 创建目录对象
        Directory directory = FSDirectory.open(new File("indexDir"));
        // 创建配置对象
        IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
        // 创建索引写出工具
        IndexWriter writer = new IndexWriter(directory, conf);
    
        // 创建新的文档数据
        Document doc = new Document();
        doc.add(new StringField("id","1",Store.YES));
        doc.add(new TextField("title","谷歌地图之父跳槽facebook ",Store.YES));
        /* 修改索引。参数:
             * 	词条:根据这个词条匹配到的所有文档都会被修改
             * 	文档信息:要修改的新的文档数据
             */
        writer.updateDocument(new Term("id","1"), doc);
        // 提交
        writer.commit();
        // 关闭
        writer.close();
    }
    

    5.5 删除索引

    步骤:

    //1 创建文档对象目录

    //2 创建索引写入器配置对象

    //3 创建索引写入器

    //4 删除

    //5 提交

    //6 关闭

    /*
         * 演示:删除索引
         * 注意:
         * 	一般,为了进行精确删除,我们会根据唯一字段来删除。比如ID
         * 	如果是用Term删除,要求ID也必须是字符串类型!
         */
    @Test
    public void testDelete() throws Exception {
        // 创建目录对象
        Directory directory = FSDirectory.open(new File("indexDir"));
        // 创建配置对象
        IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
        // 创建索引写出工具
        IndexWriter writer = new IndexWriter(directory, conf);
    
        // 根据词条进行删除
        //		writer.deleteDocuments(new Term("id", "1"));
    
        // 根据query对象删除,如果ID是数值类型,那么我们可以用数值范围查询锁定一个具体的ID
        //		Query query = NumericRangeQuery.newLongRange("id", 2L, 2L, true, true);
        //		writer.deleteDocuments(query);
    
        // 删除所有
        writer.deleteAll();
        // 提交
        writer.commit();
        // 关闭
        writer.close();
    }
    

    6 Lucene的高级使用

    6.1 高亮显示

    原理:

    1)给所有关键字加上一个HTML标签

    在这里插入图片描述

    2)给这个特殊的标签设置CSS样式

    在这里插入图片描述

    实现步骤:

    	//1 创建目录 对象
        //2 创建索引读取工具
    
    	//3 创建索引搜索工具
    
    	//4 创建查询解析器
    
    	//5 创建查询对象
    
    	//6 创建格式化器
    
    	//7 创建查询分数工具
    
    	//8 准备高亮工具
    
    	//9 搜索
    
    	//10 获取结果
    
    	//11 用高亮工具处理普通的查询结果
    
    // 高亮显示
        @Test
        public void testHighlighter() throws Exception {
            // 目录对象
            Directory directory = FSDirectory.open(new File("indexDir"));
            // 创建读取工具
            IndexReader reader = DirectoryReader.open(directory);
            // 创建搜索工具
            IndexSearcher searcher = new IndexSearcher(reader);
    
            QueryParser parser = new QueryParser("title", new IKAnalyzer());
            Query query = parser.parse("谷歌地图");
    
            // 格式化器
            Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");
            QueryScorer scorer = new QueryScorer(query);
            // 准备高亮工具
            Highlighter highlighter = new Highlighter(formatter, scorer);
            // 搜索
            TopDocs topDocs = searcher.search(query, 10);
            System.out.println("本次搜索共" + topDocs.totalHits + "条数据");
    
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (ScoreDoc scoreDoc : scoreDocs) {
                // 获取文档编号
                int docID = scoreDoc.doc;
                Document doc = reader.document(docID);
                System.out.println("id: " + doc.get("id"));
    
                String title = doc.get("title");
                // 用高亮工具处理普通的查询结果,参数:分词器,要高亮的字段的名称,高亮字段的原始值
                String hTitle = highlighter.getBestFragment(new IKAnalyzer(), "title", title);
    
                System.out.println("title: " + hTitle);
                // 获取文档的得分
                System.out.println("得分:" + scoreDoc.score);
            }
    
        }
    

    6.2 排序

    // 排序
        @Test
        public void testSortQuery() throws Exception {
            // 目录对象
            Directory directory = FSDirectory.open(new File("indexDir"));
            // 创建读取工具
            IndexReader reader = DirectoryReader.open(directory);
            // 创建搜索工具
            IndexSearcher searcher = new IndexSearcher(reader);
    
            QueryParser parser = new QueryParser("title", new IKAnalyzer());
            Query query = parser.parse("谷歌地图");
    
            // 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
            Sort sort = new Sort(new SortField("id", SortField.Type.LONG, true));
            // 搜索
            TopDocs topDocs = searcher.search(query, 10,sort);
            System.out.println("本次搜索共" + topDocs.totalHits + "条数据");
    
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (ScoreDoc scoreDoc : scoreDocs) {
                // 获取文档编号
                int docID = scoreDoc.doc;
                Document doc = reader.document(docID);
                System.out.println("id: " + doc.get("id"));
                System.out.println("title: " + doc.get("title"));
            }
        }
    

    6.3 分页

    // 分页
    	@Test
    	public void testPageQuery() throws Exception {
    		// 实际上Lucene本身不支持分页。因此我们需要自己进行逻辑分页。我们要准备分页参数:
    		int pageSize = 2;// 每页条数
    		int pageNum = 3;// 当前页码
    		int start = (pageNum - 1) * pageSize;// 当前页的起始条数
    		int end = start + pageSize;// 当前页的结束条数(不能包含)
    		
    		// 目录对象
    		Directory directory = FSDirectory.open(new File("indexDir"));
    		// 创建读取工具
    		IndexReader reader = DirectoryReader.open(directory);
    		// 创建搜索工具
    		IndexSearcher searcher = new IndexSearcher(reader);
    		
    		QueryParser parser = new QueryParser("title", new IKAnalyzer());
    		Query query = parser.parse("谷歌地图");
    		
    		// 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
    		Sort sort = new Sort(new SortField("id", Type.LONG, false));
    		// 搜索数据,查询0~end条
    		TopDocs topDocs = searcher.search(query, end,sort);
    		System.out.println("本次搜索共" + topDocs.totalHits + "条数据");
    		
    		ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    		for (int i = start; i < end; i++) {
    			ScoreDoc scoreDoc = scoreDocs[i];
    			// 获取文档编号
    			int docID = scoreDoc.doc;
    			Document doc = reader.document(docID);
    			System.out.println("id: " + doc.get("id"));
    			System.out.println("title: " + doc.get("title"));
    		}
    	}
    

    6.4 得分算法

    l Lucene会对搜索结果打分,用来表示文档数据与词条关联性的强弱,得分越高,表示查询的匹配度就越高,排名就越靠前!其算法公式是:

    在这里插入图片描述

    在这里插入图片描述


    展开全文
  • lucene学习笔记

    千次阅读 2018-11-11 08:48:33
    1 Lucene 全文检索技术 2 lucene介绍 2.1 什么是lucene Lucene是Apache的一个全文检索引擎工具包,通过lucene可以让程序员快速开发一个全文检索功能。 引擎:核心组件 工具包:jar包、类库 2.2 全文检索的应用场景 ...

    1 Lucene 全文检索技术

    2 lucene介绍

    2.1 什么是lucene

    Lucene是Apache的一个全文检索引擎工具包,通过lucene可以让程序员快速开发一个全文检索功能。

    引擎:核心组件
    工具包:jar包、类库

    2.2 全文检索的应用场景

    2.2.1 搜索引擎

    在这里插入图片描述

    2.2.2 站内搜索(关注)

    在这里插入图片描述

    2.2.3 文件系统的搜索

    在这里插入图片描述

    2.2.4 总结

    Lucene和搜索引擎不是一回事

    Lucene是一个工具包,它不能独立运行,不能单独对外提供服务。
    搜索引擎可以独立运行对外提供搜索服务。

    2.3 全文检索的定义

    全文检索首先对要搜索的文档进行分词,然后形成索引,通过查询索引来查询文档。

    全文检索就是先创建索引,然后根据索引来进行搜索的过程,就叫全文检索。

    比如:字典,
    字典的偏旁部首页,就类似于luence的索引
    字典的具体内容,就类似于luence的文档内容

    3 Lucene实现全文检索的流程

    在这里插入图片描述

    全文检索的流程:索引流程、搜索流程

    索引流程:采集数据—》文档处理存储到索引库中
    搜索流程:输入查询条件—》通过lucene的查询器查询索引—》从索引库中取出结—》视图渲染

    Lucene本身不能进行视图渲染。

    4 入门程序

    4.1 需求

    使用lucene完成对数据库中图书信息的索引和搜索功能。

    4.2 环境准备

    • Jdk:1.7及以上
    • Lucene:4.10(从4.8版本以后,必须使用jdk1.7及以上)
    • Ide:indigo
    • 数据库:mysql 5

    4.2.1 数据库脚本初始化

    在这里插入图片描述

    4.2.2 Lucene下载

    Lucene是开发全文检索功能的工具包,使用时从官方网站下载,并解压。

    官方网站:http://lucene.apache.org/
    目前最新版本:5.4.0

    下载地址:http://archive.apache.org/dist/lucene/java/

    下载版本:4.10.3
    JDK要求:1.7以上(从版本4.8开始,不支持1.7以下)
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    4.3 工程搭建

    • Mysql驱动包
    • Analysis的包
    • Core包
    • QueryParser包
    • Junit包(非必须)
      在这里插入图片描述

    4.4 索引流程

    4.4.1 为什么采集数据

    全文检索搜索的内容的格式是多种多样的,比如:视频、mp3、图片、文档等等。对于这种格式不同的数据,需要先将他们采集到本地,然后统一封装到lucene的文档对象中,也就是说需要将存储的内容进行统一才能对它进行查询。

    4.4.2 采集数据的方式

    • 对于互联网中的数据,使用爬虫工具(http工具)将网页爬取到本地
    • 对于数据库中的数据,使用jdbc程序进行数据采集
    • 对于文件系统的数据,使用io流采集

    因为目前搜索引擎主要搜索数据的来源是互联网,搜索引擎使用一种爬虫程序抓取网页( 通过http抓取html网页信息),以下是一些爬虫项目:
    Solr(http://lucene.apache.org/solr) ,solr是apache的一个子项目,支持从关系数据库、xml文档中提取原始数据。
    Nutch(http://lucene.apache.org/nutch), Nutch是apache的一个子项目,包括大规模爬虫工具,能够抓取和分辨web网站数据。
    jsoup(http://jsoup.org/ ),jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
    heritrix(http://sourceforge.net/projects/archive-crawler/files/),Heritrix 是一个由 java 开发的、开源的网络爬虫,用户可以使用它来从网上抓取想要的资源。其最出色之处在于它良好的可扩展性,方便用户实现自己的抓取逻辑。

    4.4.3 索引文件的逻辑结构

    • 文档域
      文档域存储的信息就是采集到的信息,通过Document对象来存储,具体说是通过Document对象中field域来存储数据。

    比如:数据库中一条记录会存储一个一个Document对象,数据库中一列会存储成Document中一个field域。

    文档域中,Document对象之间是没有关系的。而且每个Document中的field域也不一定一样。

    • 索引域

    索引域主要是为了搜索使用的。索引域内容是经过lucene分词之后存储的。

    • 倒排索引表

    传统方法是先找到文件,如何在文件中找内容,在文件内容中匹配搜索关键字,这种方法是顺序扫描方法,数据量大就搜索慢。
    倒排索引结构是根据内容(词语)找文档,倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它是在索引中匹配搜索关键字,由于索引内容量有限并且采用固定优化算法搜索速度很快,找到了索引中的词汇,词汇与文档关联,从而最终找到了文档。
    在这里插入图片描述

    4.4.4 索引

    4.4.4.1 采集数据

    在这里插入图片描述

    public class BookDaoImpl implements BookDao {
    
    	@Override
    	public List<Book> queryBooks() {
    		// 数据库链接
    		Connection connection = null;
    
    		// 预编译statement
    		PreparedStatement preparedStatement = null;
    
    		// 结果集
    		ResultSet resultSet = null;
    
    		// 图书列表
    		List<Book> list = new ArrayList<Book>();
    
    		try {
    			// 加载数据库驱动
    			Class.forName("com.mysql.jdbc.Driver");
    			// 连接数据库
    			connection = DriverManager.getConnection(
    					"jdbc:mysql://localhost:3306/solr", "root", "root");
    
    			// SQL语句
    			String sql = "SELECT * FROM book";
    			// 创建preparedStatement
    			preparedStatement = connection.prepareStatement(sql);
    
    			// 获取结果集
    			resultSet = preparedStatement.executeQuery();
    
    			// 结果集解析
    			while (resultSet.next()) {
    				Book book = new Book();
    				book.setId(resultSet.getInt("id"));
    				book.setName(resultSet.getString("name"));
    				book.setPrice(resultSet.getFloat("price"));
    				book.setPic(resultSet.getString("pic"));
    				book.setDescription(resultSet.getString("description"));
    				list.add(book);
    			}
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    		return list;
    	}
    
    }
    
    

    4.4.4.2 创建索引

    创建索引流程:
    在这里插入图片描述

    IndexWriter是索引过程的核心组件,通过IndexWriter可以创建新索引、更新索引、删除索引操作。IndexWriter需要通过Directory对索引进行存储操作。
    Directory描述了索引的存储位置,底层封装了I/O操作,负责对索引进行存储。它是一个抽象类,它的子类常用的包括FSDirectory(在文件系统存储索引)、RAMDirectory(在内存存储索引)。

    @Test
    	public void createIndex() throws Exception {
    		// 采集数据
    		BookDao dao = new BookDaoImpl();
    		List<Book> list = dao.queryBooks();
    
    		// 将采集到的数据封装到Document对象中
    		List<Document> docList = new ArrayList<>();
    		Document document;
    		for (Book book : list) {
    			document = new Document();
    			// store:如果是yes,则说明存储到文档域中
    			// 图书ID
    			Field id = new TextField("id", book.getId().toString(), Store.YES);
    			// 图书名称
    			Field name = new TextField("name", book.getName(), Store.YES);
    			// 图书价格
    			Field price = new TextField("price", book.getPrice().toString(),
    					Store.YES);
    			// 图书图片地址
    			Field pic = new TextField("pic", book.getPic(), Store.YES);
    			// 图书描述
    			Field description = new TextField("description",
    					book.getDescription(), Store.YES);
    
    			// 将field域设置到Document对象中
    			document.add(id);
    			document.add(name);
    			document.add(price);
    			document.add(pic);
    			document.add(description);
    
    			docList.add(document);
    		}
    
    		// 创建分词器,标准分词器
    		Analyzer analyzer = new StandardAnalyzer();
    
    		// 创建IndexWriter
    		IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
    				analyzer);
    		// 指定索引库的地址
    		File indexFile = new File("E:\\11-index\\hm19\\");
    		Directory directory = FSDirectory.open(indexFile);
    		IndexWriter writer = new IndexWriter(directory, cfg);
    
    		// 通过IndexWriter对象将Document写入到索引库中
    		for (Document doc : docList) {
    			writer.addDocument(doc);
    		}
    
    		// 关闭writer
    		writer.close();
    	}
    
    

    4.4.4.3 分词

    Lucene中分词主要分为两个步骤:分词、过滤

    分词:将field域中的内容一个个的分词。
    过滤:将分好的词进行过滤,比如去掉标点符号、大写转小写、词的型还原(复数转单数、过去式转成现在式)、停用词过滤

    停用词:单独应用没有特殊意义的词。比如的、啊、等,英文中的this is a the等等。
     要分词的内容
    Lucene is a Java full-text search engine.

    分词
    Lucene
    is
    a
    Java
    Full

    text
    search
    engine
    .

    过滤

    去掉标点符号
    Lucene
    is
    a
    Java
    Full
    text
    search
    engine

    去掉停用词
    Lucene
    Java
    Full
    text
    search
    engine

    大写转小写
    lucene
    java
    full
    text
    search
    engine

    如下是org.apache.lucene.analysis.standard.standardAnalyzer的部分源码:

    @Override
      protected TokenStreamComponents createComponents(final String fieldName, final Reader reader) {
        final StandardTokenizer src = new StandardTokenizer(getVersion(), reader);
        src.setMaxTokenLength(maxTokenLength);
        TokenStream tok = new StandardFilter(getVersion(), src);
        tok = new LowerCaseFilter(getVersion(), tok);
        tok = new StopFilter(getVersion(), tok, stopwords);
        return new TokenStreamComponents(src, tok) {
          @Override
          protected void setReader(final Reader reader) throws IOException {
            src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
            super.setReader(reader);
          }
        };
      }
    
    

    如下图是语汇单元的生成过程:
    在这里插入图片描述

    从一个Reader字符流开始,创建一个基于Reader的Tokenizer分词器,经过三个TokenFilter生成语汇单元Token。

    同一个域中相同的语汇单元(Token)对应同一个Term(词),它记录了语汇单元的内容及所在域的域名等,还包括来该token出现的频率及位置。

    • 不同的域中拆分出来的相同的单词对应不同的term。
    • 相同的域中拆分出来的相同的单词对应相同的term。
      例如:图书信息里面,图书名称中的java和图书描述中的java对应不同的term

    4.4.4.4 使用luke工具查看索引

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    4.5 搜索流程

    4.5.1 输入查询语句

    同数据库的sql一样,lucene全文检索也有固定的语法:
    最基本的有比如:AND, OR, NOT 等

    举个例子,用户想找一个description中包括java关键字和lucene关键字的文档。
    它对应的查询语句:description:java AND lucene
    如下是使用luke搜索的例子:
    在这里插入图片描述

    4.5.2 代码

    在这里插入图片描述

    @Test
    	public void indexSearch() throws Exception {
    		// 创建query对象
    		// 使用QueryParser搜索时,需要指定分词器,搜索时的分词器要和索引时的分词器一致
    		// 第一个参数:默认搜索的域的名称
    		QueryParser parser = new QueryParser("description",
    				new StandardAnalyzer());
    
    		// 通过queryparser来创建query对象
    		// 参数:输入的lucene的查询语句(关键字一定要大写)
    		Query query = parser.parse("description:java AND lucene");
    
    		// 创建IndexSearcher
    		// 指定索引库的地址
    		File indexFile = new File("E:\\11-index\\hm19\\");
    		Directory directory = FSDirectory.open(indexFile);
    		IndexReader reader = DirectoryReader.open(directory);
    		IndexSearcher searcher = new IndexSearcher(reader);
    
    		// 通过searcher来搜索索引库
    		// 第二个参数:指定需要显示的顶部记录的N条
    		TopDocs topDocs = searcher.search(query, 10);
    
    		// 根据查询条件匹配出的记录总数
    		int count = topDocs.totalHits;
    		System.out.println("匹配出的记录总数:" + count);
    		// 根据查询条件匹配出的记录
    		ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    
    		for (ScoreDoc scoreDoc : scoreDocs) {
    			// 获取文档的ID
    			int docId = scoreDoc.doc;
    
    			// 通过ID获取文档
    			Document doc = searcher.doc(docId);
    			System.out.println("商品ID:" + doc.get("id"));
    			System.out.println("商品名称:" + doc.get("name"));
    			System.out.println("商品价格:" + doc.get("price"));
    			System.out.println("商品图片地址:" + doc.get("pic"));
    			System.out.println("==========================");
    			// System.out.println("商品描述:" + doc.get("description"));
    		}
    		// 关闭资源
    		reader.close();
    	}
    
    

    5 Field域

    5.1 Field的属性

    • 是否分词(Tokenized)
      是:对该field存储的内容进行分词,分词的目的,就是为了索引。

    比如:商品名称、商品描述、商品价格

    否:不需要对field存储的内容进行分词,不分词,不代表不索引,而是将整个内容进行索引。

    比如:商品id

    • 是否索引(Indexed)
      是:将分好的词进行索引,索引的目的,就是为了搜索。

    比如:商品名称、商品描述、商品价格、商品id

    否:不索引,也就是不对该field域进行搜索。

    • 是否存储(Stored)
      是:将field域中的内容存储到文档域中。存储的目的,就是为了搜索页面显示取值用的。

    比如:商品名称、商品价格、商品id、商品图片地址

    否:不将field域中的内容存储到文档域中。不存储,则搜索页面中没法获取该field域的值。

    比如:商品描述,由于商品描述在搜索页面中不需要显示,再加上商品描述的内容比较多,所以就不需要进行存储。

    如果需要商品描述,则根据搜索出的商品ID去数据库中查询,然后显示出商品描述信息即可。

    5.2 Field的常用类型

    下边列出了开发中常用 的Filed类型,注意Field的属性,根据需求选择:

    Field类 数据类型 Analyzed是否分词 Indexed是否索引 Stored是否存储 说明
    StringField(FieldName, FieldValue,Store.YES)) 字符串 N Y Y或N 这个Field用来构建一个字符串Field,但是不会进行分词,会将整个串存储在索引中,比如(订单号,身份证号等)是否存储在文档中用Store.YES或Store.NO决定
    LongField(FieldName, FieldValue,Store.YES) Long型 Y N Y或N 这个Field用来构建一个Long数字型Field,进行分词和索引,比如(价格)是否存储在文档中用Store.YES或Store.NO决定
    StoredField(FieldName, FieldValue) 重载方法,支持多种类型 N N Y 这个Field用来构建不同类型Field不分析,不索引,但要Field存储在文档中
    TextField(FieldName, FieldValue, Store.NO)或TextField(FieldName, reader) 字符串或流 Y Y Y或N 如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.

    5.3 修改入门程序的代码

    在这里插入图片描述

    6 索引维护

    6.1 需求

    图书信息在数据库 发生变化,所以索引库相对应的也要发生增删改变化。

    6.2 添加索引

    参考入门程序的索引流程
    IndexWriter.addDocument(document);

    6.3 删除索引

    增删改操作,都是需要通过IndexWriter对象来操作

    6.3.1 根据条件删除

    Term是索引域中最小的单位。根据条件删除时,建议根据唯一键来进行删除。在solr中就是根据ID来进行删除和修改操作的。
    在这里插入图片描述

    6.3.2 删除全部

    6.4 修改索引

    在这里插入图片描述

    7 搜索

    7.1 创建查询对象的方式

    • 通过Query子类来创建查询对象
      Query子类常用的有:TermQuery、NumericRangeQuery、BooleanQuery

    不能输入lucene的查询语法,不需要指定分词器

    • 通过QueryParser来创建查询对象(常用)
      QueryParser、MultiFieldQueryParser

    可以输入lucene的查询语法、可以指定分词器

    7.2 通过Query子类来创建查询对象

    7.2.1 TermQuery

    精确的词项查询

    在这里插入图片描述

    7.2.2 NumericRangeQuery

    数字范围查询
    在这里插入图片描述

    7.2.3 BooleanQuery

    组合查询
    在这里插入图片描述

    组合关系代表的意思如下:
    1、MUST和MUST表示“与”的关系,即“并集”。
    2、MUST和MUST_NOT前者包含后者不包含。
    3、MUST_NOT和MUST_NOT没意义
    4、SHOULD与MUST表示MUST,SHOULD失去意义;
    5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
    6、SHOULD与SHOULD表示“或”的概念。

    7.3 通过QueryParser创建查询对象

    7.3.1 QueryParser

    通过QueryParser来创建query对象,可以指定分词器,搜索时的分词器和创建该索引的分词器一定要一致。还可以输入查询语句。

    参考入门程序之搜索流程。

    7.3.2 MultiFieldQueryParser

    多域查询
    在这里插入图片描述

    7.3.3 查询语法

    1、基础的查询语法,关键词查询:
    域名+“:”+搜索的关键字
    例如:content:java
    2、范围查询
    域名+“:”+[最小值 TO 最大值]
    例如:size:[1 TO 1000]
    注意:QueryParser不支持对数字范围的搜索,它支持字符串范围。数字范围搜索建议使用NumericRangeQuery。
    3、组合条件查询

    Occur.MUST 查询条件必须满足,相当于and +(加号)
    Occur.MUST_NOT 查询条件不能满足,相当于not非 -(减号)
    Occur.SHOULD 查询条件可选,相当于or 空(不用符号)

    1)+条件1 +条件2:两个条件之间是并且的关系and
    例如:+filename:apache +content:apache
    2)+条件1 条件2:必须满足第一个条件,忽略第二个条件
    例如:+filename:apache content:apache
    3)条件1 条件2:两个条件满足其一即可。
    例如:filename:apache content:apache
    4)-条件1 条件2:必须不满足条件1,要满足条件2
    例如:-filename:apache content:apache

    第二种写法:
    条件1 AND 条件2
    条件1 OR 条件2
    条件1 NOT 条件2

    7.4 TopDocs

    Lucene搜索结果可通过TopDocs遍历,TopDocs类提供了少量的属性,如下:

    方法或属性 说明
    totalHits 匹配搜索条件的总记录数
    scoreDocs 顶部匹配记录

    注意:
    Search方法需要指定匹配记录数量n:indexSearcher.search(query, n)
    TopDocs.totalHits:是匹配索引库中所有记录的数量
    TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参数n

    8 相关度排序

    8.1 什么是相关度排序

    相关度排序就是查询关键字与查询结果的匹配相关度。匹配越高的越靠前。Lucene是通过打分来进行相关度排序的。

    打分分两步:
    1、 根据词计算词的权重
    2、 根据词的权重进行打分

    词的权重:词指的就是term。也就是说一个term对一个文档的重要性,就叫词的权重。

    影响词的权重的方式有两种:

    • Tf
      词在同一个文档中出现的频率
      Tf越高,说明词的权重越高
    • Df
      词在多个文档中出现的频率
      Df越高,说明词的权重越低

    以上是自然打分的规则。

    8.2 设置boost值影响打分

    Boost:加权值,默认是1.0f。

    设置加权值可以在创建索引时设置,也可以在查询时设置。
    Boost值是设置到Field域上的。

    8.2.1 创建索引时设置boost值

    在这里插入图片描述

    8.2.2 搜索时设置boost值

    在MultiFieldQueryParser创建时设置boost值。

    在这里插入图片描述

    9 中文分词器

    9.1 什么是中文分词器

    对于英文,是安装空格、标点符号进行分词
    对于中文,应该安装具体的词来分,中文分词就是将词,切分成一个个有意义的词。

    比如:“我的中国人”,分词:我、的、中国、中国人、国人。

    9.2 Lucene自带的中文分词器

    • StandardAnalyzer:
      单字分词:就是按照中文一个字一个字地进行分词。如:“我爱中国”,
      效果:“我”、“爱”、“中”、“国”。
    • CJKAnalyzer
      二分法分词:按两个字进行切分。如:“我是中国人”,效果:“我是”、“是中”、“中国”“国人”。

    上边两个分词器无法满足需求。

    9.3 第三方中文分词器

    • paoding: 庖丁解牛最新版在 https://code.google.com/p/paoding/ 中最多支持Lucene 3.0,且最新提交的代码在 2008-06-03,在svn中最新也是2010年提交,已经过时,不予考虑。
    • mmseg4j:最新版已从 https://code.google.com/p/mmseg4j/ 移至 https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代码是2014年6月,从09年~14年一共有:18个版本,也就是一年几乎有3个大小版本,有较大的活跃度,用了mmseg算法。
    • IK-analyzer: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词 歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 但是也就是2012年12月后没有在更新。
    • ansj_seg:最新版本在 https://github.com/NLPchina/ansj_seg tags仅有1.1版本,从2012年到2014年更新了大小6次,但是作者本人在2014年10月10日说明:“可能我以后没有精力来维护ansj_seg了”,现在由”nlp_china”管理。2014年11月有更新。并未说明是否支持Lucene,是一个由CRF(条件随机场)算法所做的分词算法。
    • imdict-chinese-analyzer:最新版在 https://code.google.com/p/imdict-chinese-analyzer/ , 最新更新也在2009年5月,下载源码,不支持Lucene 4.10 。是利用HMM(隐马尔科夫链)算法。
    • Jcseg:最新版本在git.oschina.net/lionsoul/jcseg,支持Lucene 4.10,作者有较高的活跃度。利用mmseg算法。

    9.4 Ikanalyzer

    在这里插入图片描述

    9.4.1 添加ikanalyzer的jar包

    在这里插入图片描述

    9.4.2 代码

    在这里插入图片描述

    9.4.3 扩展中文词库

    将以下文件拷贝到config目录下
    在这里插入图片描述

    从ikanalyzer包中拷贝配置文件到classpath下。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
    <properties>  
    
        <comment>IK Analyzer 扩展配置</comment>
        <!-- 用户可以在这里配置自己的扩展字典 -->
         <entry key="ext_dict">dicdata/mydict.dic</entry> 
         <!-- 用户可以在这里配置自己的扩展停用词字典    -->
        <entry key="ext_stopwords">dicdata/ext_stopword.dic</entry> 
    
    </properties>
    

    如果想配置扩展词和停用词,就创建扩展词的文件和停用词的文件,文件的编码要是utf-8。
    注意:不要用记事本保存扩展词文件和停用词文件,那样的话,格式中是含有bom的。

    9.4.4 使用luke来查询中文分词效果

    第一步:将ikanalyzer的jar包,拷贝到luke工具的目录

    在这里插入图片描述

    第二步:使用命令打开luke工具
    java -Djava.ext.dirs=. -jar lukeall-4.10.3.jar

    展开全文
  • 1、什么是LuceneLucene能干什么

    千次阅读 2016-06-17 16:52:14
    1、什么是lucene  Lucene是一个全文搜索框架,而不是应用产品。因此它并不像http://www.baidu.com/ 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。    2、lucene能做什么...
    1、什么是lucene 
    Lucene是一个全文搜索框架,而不是应用产品。因此它并不像http://www.baidu.com/ 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。 
     
    2、lucene能做什么  
    要回答这个问题,先要了解lucene的本质。实际上lucene的功能很单一,说到底,就是你给它若干个字符串,然后它为你提供一个全文搜索服务,告诉你你要搜索的关键词出现在哪里。知道了这个本质,你就可以发挥想象做任何符合这个条件的事情了。你可以把站内新闻都索引了,做个资料库;你可以把一个数据库表的若干个字段索引起来,那就不用再担心因为“%like%”而锁表了;你也可以写个自己的搜索引擎…… 
     
    3、lucene的性能怎么样
    下面给出一些测试数据,如果你觉得可以接受,那么可以选择。  
    测试一:250万记录,300M左右文本,生成索引380M左右,800线程下平均处理时间300ms。  
    测试二:37000记录,索引数据库中的两个varchar字段,索引文件2.6M,800线程下平均处理时间1.5ms。
     
    4、lucene为什么这么快
    倒排索引 :

    倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。

    倒排文件(倒排索引),索引对象是文档或者文档集合中的单词等,用来存储这些单词在一个文档或者一组文档中的存储位置,是对文档或者文档集合的一种最常用的索引机制。

    搜索引擎的关键步骤就是建立倒排索引,倒排索引一般表示为一个关键词,然后是它的频度(出现的次数),位置(出现在哪一篇文章或网页中,及有关的日期,作者等信息),它相当于为互联网上几千亿页网页做了一个索引,好比一本书的目录、标签一般。读者想看哪一个主题相关的章节,直接根据目录即可找到相关的页面。不必再从书的第一页到最后一页,一页一页的查找。

    技术分享

    更多详细请查看:

    http://www.cnblogs.com/raphael5200/p/5143687.html

    http://blog.csdn.net/chichengit/article/details/9235157

    压缩算法:
    LZ4算法又称为Realtime Compression Algorithm,在操作系统(linux/freeBSD)、文件系统(OpenZFS)、大数据(Hadoop)、搜索引擎(Lucene/solr)、数据库(Hbase)……都可以看到它的身影,可以说是一个非常通用的算法。LZ4最突出的地方在于它的压缩/解压速度。
    相关文章:
    http://blog.csdn.net/zhangskd/article/details/17009111
    http://blog.csdn.net/zhangskd/article/details/17282895
     
    二元搜索
    二元搜索算法是在排好序的数组中找到特定的元素,类似key,value
    首先, 比较数组中间的元素,如果相同,则返回此元素的指针,表示找到了. 如果不相同, 此函数就会继续搜索其中大小相符的一半,然后继续下去. 如果剩下的数组长度为0, 则表示找不到,那么函数就会结束.
      
    5、lucene的工作方式 
    lucene提供的服务实际包含两部分:一入一出。所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源 
     
    写入流程
    源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选)。  将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。  将索引写入存储器,存储器可以是内存或磁盘。
     
    读出流程 
    用户提供搜索关键词,经过analyzer处理。  对处理后的关键词搜索索引找出对应的Document。  用户根据需要从找到的Document中提取需要的Field。
     
    document 
    用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。用户进行搜索,也是以Document列表的形式返回。 
     
     field 
    一个Document可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过Field在Document中存储的。 
    Field有两个属性可选:存储和索引。通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。这看起来似乎有些废话,事实上对这两个属性的正确组合很重要 
     
    展开全文
  • Lucene7.2.1系列(一)快速入门

    万次阅读 2018-06-19 21:04:53
    Lucene系列(一)快速入门 Lucene系列(二)luke使用及索引文档的基本操作 Lucene系列(三)查询及高亮 Lucene是什么? Lucene在维基百科的定义 Lucene是一套用于全文检索和搜索的开放源代码程序库,由...

    系列文章:

    Lucene系列(一)快速入门

    Lucene系列(二)luke使用及索引文档的基本操作

    Lucene系列(三)查询及高亮

    Lucene是什么?

    Lucene在维基百科的定义

    Lucene是一套用于全文检索和搜索的开放源代码程序库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程序接口,能够做全文索引和搜索,在Java开发环境里Lucene是一个成熟的免费开放源代码工具;就其本身而论,Lucene是现在并且是这几年,最受欢迎的免费Java信息检索程序库

    另外,Lucene不提供爬虫功能,如果需要获取内容需要自己建立爬虫应用。
    Lucene只做索引和搜索工作。

    Lucene官网

    http://lucene.apache.org/

    打开Luncene官网你会发现Lucene版本更新的太快了,现在最新的版本已经是7.2.1。不过这也变相说明了Luncene这个开源库的火爆。

    Lucenesolr

    我想提到Lucene,不得不提solr了。

    很多刚接触Lucene和Solr的人都会问这个明显的问题:我应该使用Lucene还是Solr?

    答案很简单:如果你问自己这个问题,在99%的情况下,你想使用的是Solr. 形象的来说Solr和Lucene之间关系的方式是汽车及其引擎。 你不能驾驶一台发动机,但可以开一辆汽车。 同样,Lucene是一个程序化库,您不能按原样使用,而Solr是一个完整的应用程序,您可以立即使用它。(参考:Lucene vs Solr

    全文检索是什么?

    全文检索在百度百科的定义

    全文数据库是全文检索系统的主要构成部分。所谓全文数据库是将一个完整的信息源的全部内容转化为计算机可以识别、处理的信息单元而形成的数据集合。全文数据库不仅存储了信息,而且还有对全文数据进行词、字、段落等更深层次的编辑、加工的功能,而且所有全文数据库无一不是海量信息数据库。

    全文检索首先将要查询的目标文档中的词提取出来,组成索引,通过查询索引达到搜索目标文档的目的。这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。

    全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。

    全面、准确和快速是衡量全文检索系统的关键指标。

    关于全文检索,我们要知道:

    • 只处理文本。
    • 不处理语义。
    • 搜索时英文不区分大小写。
    • 结果列表有相关度排序。(查出的结果如果没有相关度排序,那么系统不知道我想要的结果在哪一页。我们在使用百度搜索时,一般不需要翻页,为什么?因为百度做了相关度排序:为每一条结果打一个分数,这条结果越符合搜索条件,得分就越高,叫做相关度得分,结果列表会按照这个分数由高到低排列,所以第1页的结果就是我们最想要的结果。)
      在信息检索工具中,全文检索是最具通用性和实用性的。

    参考:https://zhuanlan.zhihu.com/p/25558228

    全文检索和数据库搜索的区别
    >
    简单来说,这两者解决的问题是不一样。数据库搜索在匹配效果、速度、效率等方面都逊色于全文检索。下面我们的一个例子就能很清楚说明这一点。

    Lucene实现全文检索流程是什么?

    Lucene实现全文检索流程
    全文检索的流程分为两大部分:索引流程搜索流程

    • 索引流程:即采集数据构建文档对象分析文档(分词)创建索引。

    • 搜索流程:即用户通过搜索界面创建查询执行搜索,搜索器从索引库搜索渲染搜索结果

    我们在下面的一个程序中,对这个全文检索的流程会有进一步的了解。

    Lucene实现向文档写索引并读取文档

    截止2018/3/30,用到的jar包结为最新。

    程序用到的数据下载地址:

    链接:https://pan.baidu.com/s/1ccgrCCRBBGOL-fmmOLrxlQ

    密码:vyof
    1. 创建Maven项目,并添加相关jar包依赖

            <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-core -->
            <!-- Lucene核心库 -->
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-core</artifactId>
                <version>7.2.1</version>
            </dependency>
            <!-- Lucene解析库 -->
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-queryparser</artifactId>
                <version>7.2.1</version>
            </dependency>
            <!-- Lucene附加的分析库 -->
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-analyzers-common</artifactId>
                <version>7.2.1</version>
            </dependency>
    1. 向文档里写索引
    package lucene_demo1;
    
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.nio.file.Paths;
    
    import org.apache.lucene.analysis.Analyzer;
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.document.Field;
    import org.apache.lucene.document.TextField;
    import org.apache.lucene.index.IndexWriter;
    import org.apache.lucene.index.IndexWriterConfig;
    import org.apache.lucene.store.Directory;
    import org.apache.lucene.store.FSDirectory;
    /**
     * 
     *TODO  索引文件
     * @author Snaiclimb
     * @date 2018年3月30日
     * @version 1.8
     */
    public class Indexer {
        // 写索引实例
        private IndexWriter writer;
    
        /**
         * 构造方法 实例化IndexWriter
         * 
         * @param indexDir
         * @throws IOException
         */
        public Indexer(String indexDir) throws IOException {
            //得到索引所在目录的路径  
            Directory directory = FSDirectory.open(Paths.get(indexDir));
            // 标准分词器
            Analyzer analyzer = new StandardAnalyzer();
            //保存用于创建IndexWriter的所有配置。
            IndexWriterConfig iwConfig = new IndexWriterConfig(analyzer);
            //实例化IndexWriter  
            writer = new IndexWriter(directory, iwConfig);
        }
    
        /**
         * 关闭写索引
         * 
         * @throws Exception
         * @return 索引了多少个文件
         */
        public void close() throws IOException {
            writer.close();
        }
    
        public int index(String dataDir) throws Exception {
            File[] files = new File(dataDir).listFiles();
            for (File file : files) {
                //索引指定文件
                indexFile(file);
            }
            //返回索引了多少个文件
            return writer.numDocs();
    
        }
    
        /**
         * 索引指定文件
         * 
         * @param f
         */
        private void indexFile(File f) throws Exception {
            //输出索引文件的路径
            System.out.println("索引文件:" + f.getCanonicalPath());
            //获取文档,文档里再设置每个字段
            Document doc = getDocument(f);
            //开始写入,就是把文档写进了索引文件里去了;
            writer.addDocument(doc);
        }
    
        /**
         * 获取文档,文档里再设置每个字段
         * 
         * @param f
         * @return document 
         */
        private Document getDocument(File f) throws Exception {
            Document doc = new Document();
            //把设置好的索引加到Document里,以便在确定被索引文档
            doc.add(new TextField("contents", new FileReader(f)));
            //Field.Store.YES:把文件名存索引文件里,为NO就说明不需要加到索引文件里去 
            doc.add(new TextField("fileName", f.getName(), Field.Store.YES));
            //把完整路径存在索引文件里  
            doc.add(new TextField("fullPath", f.getCanonicalPath(), Field.Store.YES));
            return doc;
        }
    
        public static void main(String[] args) {
            //索引指定的文档路径
            String indexDir = "D:\\lucene\\dataindex";
            被索引数据的路径  
            String dataDir = "D:\\lucene\\data";
            Indexer indexer = null;
            int numIndexed = 0;
            //索引开始时间  
            long start = System.currentTimeMillis();
            try {
                indexer = new Indexer(indexDir);
                numIndexed = indexer.index(dataDir);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                try {
                    indexer.close();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            //索引结束时间
            long end = System.currentTimeMillis();
            System.out.println("索引:" + numIndexed + " 个文件 花费了" + (end - start) + " 毫秒");
        }
    
    }

    运行效果:
    运行效果图
    我们查看D:\lucene\dataindex文件夹。我们发现多了一些东西,这些东西就是我们马上用来全文搜索的索引。

    //索引指定的文档路径
    String indexDir = "D:\\lucene\\dataindex";
    

    D:\lucene\dataindex文件夹

    Mark博文:Lucene的索引文件格式(1)

    1. 全文检索测试
    package lucene_demo1;
    
    import java.nio.file.Paths;
    
    import org.apache.lucene.analysis.Analyzer;
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.index.DirectoryReader;
    import org.apache.lucene.index.IndexReader;
    import org.apache.lucene.queryparser.classic.QueryParser;
    import org.apache.lucene.search.IndexSearcher;
    import org.apache.lucene.search.Query;
    import org.apache.lucene.search.ScoreDoc;
    import org.apache.lucene.search.TopDocs;
    import org.apache.lucene.store.Directory;
    import org.apache.lucene.store.FSDirectory;
    /**
     * 根据索引搜索
     *TODO
     * @author Snaiclimb
     * @date 2018年3月25日
     * @version 1.8
     */
    public class Searcher {
    
        public static void search(String indexDir, String q) throws Exception {
    
            // 得到读取索引文件的路径
            Directory dir = FSDirectory.open(Paths.get(indexDir));
            // 通过dir得到的路径下的所有的文件
            IndexReader reader = DirectoryReader.open(dir);
            // 建立索引查询器
            IndexSearcher is = new IndexSearcher(reader);
            // 实例化分析器
            Analyzer analyzer = new StandardAnalyzer();
            // 建立查询解析器
            /**
             * 第一个参数是要查询的字段; 第二个参数是分析器Analyzer
             */
            QueryParser parser = new QueryParser("contents", analyzer);
            // 根据传进来的p查找
            Query query = parser.parse(q);
            // 计算索引开始时间
            long start = System.currentTimeMillis();
            // 开始查询
            /**
             * 第一个参数是通过传过来的参数来查找得到的query; 第二个参数是要出查询的行数
             */
            TopDocs hits = is.search(query, 10);
            // 计算索引结束时间
            long end = System.currentTimeMillis();
            System.out.println("匹配 " + q + " ,总共花费" + (end - start) + "毫秒" + "查询到" + hits.totalHits + "个记录");
            // 遍历hits.scoreDocs,得到scoreDoc
            /**
             * ScoreDoc:得分文档,即得到文档 scoreDocs:代表的是topDocs这个文档数组
             * 
             * @throws Exception
             */
            for (ScoreDoc scoreDoc : hits.scoreDocs) {
                Document doc = is.doc(scoreDoc.doc);
                System.out.println(doc.get("fullPath"));
            }
    
            // 关闭reader
            reader.close();
        }
    
        public static void main(String[] args) {
            String indexDir = "D:\\lucene\\dataindex";
            //我们要搜索的内容
            String q = "Jean-Philippe sdsds Barrette-LaPierre";
            try {
                search(indexDir, q);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    上面我们搜索的是:”Jean-Philippe Barrette-LaPierre”;即使你:”Jean-Philippe ssss Barrette-LaPierre”这样搜索也还是搜索到,以为Lucene对其进行了分词,对中文无效。
    全文搜索

    Lucene实现全文检索流程是什么?

    我们刚刚实现的程序已经清楚地向我们展示了Lucene实现全文检索流程,我们再来回顾一下。
    Lucene实现全文检索流程
    - 在Lucene中,采集数据(从网站爬取或连接数据库)就是为了创建索引,创建索引需要先将采集的原始数据加工为文档,再由文档分词产生索引。文档(Document) 中包含若干个Field域。
    - IndexWriter是索引过程的核心组件,通过IndexWriter可以创建新索引、更新索引、删除索引操作。IndexWriter需要通过Directory对索引进行存储操作。

    • Directory描述了索引的存储位置,底层封装了I/O操作,负责对索引进行存储。它是一个抽象类,它的子类常用的包括FSDirectory(在文件系统存储索引)、RAMDirectory(在内存存储索引)。
    • 在对Docuemnt中的内容索引之前需要使用分词器进行分词 ,分词的主要过程就是分词、过滤两步。 分词就是将采集到的文档内容切分成一个一个的词,具体应该说是将Document中Field的value值切分成一个一个的词。
      过滤包括去除标点符号、去除停用词(的、是、a、an、the等)、大写转小写、词的形还原(复数形式转成单数形参、过去式转成现在式等)。
    • 停用词是为节省存储空间和提高搜索效率,搜索引擎在索引页面或处理搜索请求时会自动忽略某些字或词,这些字或词即被称为Stop Words(停用词)。比如语气助词、副词、介词、连接词等,通常自身并无明确的意义,只有将其放入一个完整的句子中才有一定作用,如常见的“的”、“在”、“是”、“啊”等。
      Lucene中自带了StandardAnalyzer,它可以对英文进行分词。

    参照:https://zhuanlan.zhihu.com/p/25558228

    欢迎关注我的微信公众号(分享各种Java学习资源,面试题,以及企业级Java实战项目回复关键字免费领取):
    微信公众号

    Lucene我想暂时先更新到这里,仅仅这三篇文章想掌握Lucene是远远不够的。另外我这里三篇文章都用的最新的jar包,Lucene更新太快,5系列后的版本和之前的有些地方还是有挺大差距的,就比如为文档域设置权值的setBoost方法6.6以后已经被废除了等等。因为时间有限,所以我就草草的看了一下Lucene的官方文档,大多数内容还是看java1234网站的这个视频来学习的,然后在版本和部分代码上做了改进。截止2018/4/1,上述代码所用的jar包皆为最新。

    最后推荐一下自己觉得还不错的Lucene学习网站/博客:

    官方网站:[Welcome to Apache Lucene](Welcome to Apache Lucene)

    Github:Apache Lucene and Solr

    Lucene专栏

    搜索系统18:lucene索引文件结构

    Lucene6.6的介绍和使用

    展开全文
  • Lucene_简介

    万次阅读 2017-12-14 15:09:43
    Lucene概述Lucene是一款高性能的、可扩展的信息检索(IR)工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。 索引过程:①获取内容②建立文档 获取原始内容后,就需要对这些内容进行...
  • lucene详细使用教程

    2020-07-29 14:20:27
    lucene
  • Lucene的使用,Lucene入门

    千次阅读 2018-05-31 23:33:15
    本文主要介绍几个方面,为什么使用Lucene使用场景,解决的问题,Lucene的入门使用,以及Lucene一些语法(增删改查)。一简述Lucene概念:磁盘上的一些邮件,文档等各种文件,通过工具,把其变得有结构性,就是他们的...
  • Lucene7.4 初体验

    千次阅读 2018-08-18 16:32:22
    前言 本文的简要内容: Lucene简介 体验Lucene Demo ...Lucene通常用于全文检索,Lucene具有简单高效跨平台等特点,因此有不少搜索引擎都是基于Lucene构建的,例如:Elasticsearch,Solr等等。 现...
  • lucene教程

    千次阅读 2018-08-23 18:39:40
    Lucene的架构设计及介绍  这个架构分为两部分,一是建立索引,从数据源建立相应的索引机制,二是索引查询,输入关键词,根据索引,查找并且返回结果。 1.lucene包 org.apache.Lucene.search/ 搜索入口 ...
  • Lucene

    2019-09-06 10:56:39
    常见企业级搜索服务器 Lucene : https://lucene.apache.org/ Solr : http://lucene.apache.org/solr/resources.html Elasticsearch : ... 一、Luence是什么? ...Lucene是一个基于Java的全文信息检索...
  • 一、Lucene介绍1. Lucene简介 最受欢迎的java开源全文搜索引擎开发工具包。提供了完整的查询引擎和索引引擎,部分文本分词引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包...
  • lucene各版本jar包下载地址

    万次阅读 2016-02-05 10:56:31
    http://archive.apache.org/dist/lucene/java/
  • maven中添加lucene支持依赖

    千次阅读 2017-06-10 08:53:25
    org.apache.lucene lucene-core 5.3.1 org.apache.lucene lucene-analyzers-common 5.3.1 org.apache.lucene lucene-analyzers-smartcn 5.3.1 org.apache.lucene
  • 不选择使用Lucene的6大原因

    万次阅读 热门讨论 2008-03-23 12:37:00
    不选择使用Lucene的6大原因 Lucene是开放源代码的全文搜索引擎工具包,凭借着其强劲的搜索功能和简单易用的实现,在国内已经很普及,甚至一度出现了言搜索必称Lucene的盛景。上个月Lucene的开发团队发布了 Java ...
  • Lucene 和solr的区别

    千次阅读 2018-08-14 09:04:48
    solr和lucene的区别: A simple way to conceptualize the relationship between Solr and Lucene is that of a car and its engine. You can't drive an engine, but you can drive a car. Similarly, Lucene is a...
  • Lucene、solr以及elasticsearch之间的区别和联系

    万次阅读 多人点赞 2018-03-05 16:06:57
    首先分别说明三者的概念:Lucene是一套信息检索工具包,并不包含搜索引擎系统,它包含了索引结构、读写索引工具、相关性工具、排序等功能,因此在使用Lucene时仍需要关注搜索引擎系统,例如数据获取、解析、分词等...
  • Lucene安装及环境配置

    千次阅读 2018-03-29 16:19:18
    1、Lucene下载 目前最新的Lucene版本是Lucene-6.6.3,官方下载传送门:地址 1、点击进入,然后选择推荐的镜像地址进入 2、随便选择一个格式的压缩文件下载即可,这里选择的是zip文件 3、下载后直接解压到...
  • lucene已经发展到了4.1.0,但是在网上还没有lucene4.1.0的配置的相关文章,一般网上关于lucene的配置都是要在环境变量的CLASSPATH中添加lucene的位置。比如:“D:/java /lucene/lucene-core-4.1.0.jar;”我尝试了n次...
  • Lucene的简单配置与测试

    千次阅读 2010-05-12 08:36:00
    全文检索引擎Lucene安装非常简单,配置完成相关的JDK环境,只需下载最新的开发包,并指定相关的路径即可支持开发和检索服务了。1. 下载lucene系统访问官方网站http://lucene.apache.org/,可以获取最新发布的Lucene...
  • Lucene和ES的区别

    千次阅读 2019-04-12 15:49:14
    Lucene和ES的区别 定义: Lucene是一个java信息检索程序库。您可以将其包含在项目中,并使用函数调用来参考其功能。 Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,...
1 2 3 4 5 ... 20
收藏数 79,822
精华内容 31,928
关键字:

lucene