Lucene 8 简单的介绍

Lucene 简介

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。

上面这段摘自百度百科,复制粘贴来的.
ElasticSearch 就是基于Lucene开发的搜索引擎,但是这篇文章我们不介绍ES

原理

比如现在主流的Bing Google Baidu Shodan 等等,都应用到了搜索技术
而这种技术实现,只用关系型存储数据库是无法实现的,哪怕你使用模糊查询,这样效率是极其低下的。
也许你会想,我也可以先建个表用来存储分词,然后多对多关系映射文章id,实际上如果你有这个想法,那么恭喜你,这差不多就是倒排索引的思路。

  • 通过下面这个例子 可以简单的了解搜索引擎的原理
    一篇文章的标题为 “21世纪以来最大的数据泄露事件”
    如果单纯使用存储数据库,人家搜索21世纪,数据泄露,等等关键词,你只能通过模糊查询多次,匹配这些关键词,然后自己计算分值,再排序
    如果数据量偏大,这种实现是根本不可能应用的,所以出现了倒排索引这种想法。

  • 倒排索引在这里插入图片描述
    这个图是我复制来的,清晰明了的看懂这种实现方式的具体原理。

  • 分词
    举个例子:“今天的天气真好啊”
    那么我们可以先排除用不到的冠词、介词、副词或连词等,也就是Lucene中的停止词StopWord
    上面这句话先将 “的” 、“啊”这两个字排除掉,剩下的再分词
    “今天”、“天气”、“真好”

  • 得分算法
    Lucene会对搜索结果打分,用来表示文档数据与词条关联性的强弱,得分越高,表示查询的匹配度就越高,排名就越靠前!
    具体可以看这里 https://blog.csdn.net/shirdrn/article/details/6785385

Lucene 代码例子

Maven Pom依赖

    <properties>
        <lunece.version>8.5.0</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>
        <!-- ik分词器 -->
        <dependency>
            <groupId>com.jianggujin</groupId>
            <artifactId>IKAnalyzer-lucene</artifactId>
            <version>8.0.0</version>
        </dependency>
    </dependencies>

创建 索引 文档

可以批量创建文档写入时直接传Collection对象,下面只创建了一个

 	@Test
    public void testCreate() throws Exception{
        //1 创建文档对象
        Document document = new Document();
        // 创建并添加字段信息。参数:字段的名称、字段的值、是否存储,这里选Store.YES代表存储到文档列表。Store.NO代表不存储
        //由于 6x版本以后 IntField LongField都没了
        document.add(new LongPoint("id", 1));//可以用来范围搜索
		document.add(new NumericDocValuesField("id", 1));//可以用来sort排序
        document.add(new StoredField("id", 1));//单纯用来获得ID值
        document.add(new StringField("tag", "小道消息", Field.Store.YES));
        // 这里我们title字段需要用TextField,即创建索引又会被分词。StringField会创建索引,但是不会被分词
        document.add(new TextField("title", "谷歌突然宕机三小时", Field.Store.YES));

        //2 索引目录类,指定索引在硬盘中的位置
        //新版本不是给File对象,需要传一个Path对象
        Directory directory = FSDirectory.open(Paths.get("D:\\indexTestDir\\"));
        //如果不想存储在硬盘可以使用RAM存储。Directory directory=new RAMDirectory();
        
        //3 创建分词器对象
        //标准分词器,并不合适中文分词,因此一般我们会用第三方提供的分词器:(比如 ChineseAnalyzer CollationAnalyzer等等,不过ChineseAnalyzer已经废弃了),这里使用的是IK分词器
        Analyzer analyzer = new IKAnalyzer();
        
        //4 索引写出工具的配置对象
        IndexWriterConfig conf = new IndexWriterConfig(analyzer);
        conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); 
        
        //5 创建索引的写出工具类。参数:索引的目录和配置信息
        IndexWriter indexWriter = new IndexWriter(directory, conf);
        
        //6 把文档交给IndexWriter
        indexWriter.addDocument(document);
        //7 提交
        indexWriter.commit();
        //8 关闭
        indexWriter.close();
    }

搜索

	@Test
    public void testSearch() throws Exception {
        // 索引目录对象
        Directory directory = FSDirectory.open(Paths.get("D:\\indexTestDir\\"));
        // 索引读取工具
        IndexReader reader = DirectoryReader.open(directory);
        // 索引搜索工具
        IndexSearcher searcher = new IndexSearcher(reader);

        // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器
        QueryParser parser = new QueryParser("title", new IKAnalyzer());
		//如果想同时匹配多个
		//QueryParser parser = new MultiFieldQueryParser(new String[]{"field1", "field2"}, 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("tag: " + doc.get("tag"));
            System.out.println("title: " + doc.get("title"));
            // 取出文档得分
            System.out.println("得分: " + scoreDoc.score);
        }
    }

更多用法

  • 精准匹配
    Query query = new TermQuery(new Term(“title”,“谷歌”));
  • 模糊查询
    Query query = new WildcardQuery(new Term(“title”, “”));
  • LongPoint 范围匹配
    Query query=LongPoint.newRangeQuery(“id”,0,10);
  • 搜索排序
    Sort sort = new Sort(new SortField(“id”, SortField.Type.LONG, true));
    TopDocs topDocs = searcher.search(query, 10,sort);
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事干写博客玩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值