page contents

java lucene 教程——什么是Lucene

本文讲述了Java lucene 教程——什么是Lucene!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2023-07-ULYYB1g364a8be812ffe6.jpg本文讲述了Java lucene 教程——什么是Lucene!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

Lucene是一套用于全文检索和搜索的开放源码程序库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程序接口,能够做全文索引和搜索。Lucene是现在最受欢迎的免费Java信息检索程序库。

全文检索(Full Text Retrieval)全文检索是指以全部文本信息作为检索对象的一种信息检索技术。最为常见的全文检索搜索引擎就是google和百度了,他们通过对互联网上的所有网页内容进行分析,索引,提供给我们秒级的搜索体验。其次,当前移动端各种APP,很多都内置了搜索功能,这些也是垂直领域的搜索实现。他们与google/百度的区别就是,只提供当前APP内信息的搜索,而不是互联网上的所有网页。

假设有10篇文章,每一篇都有标题和正文。当我们想找到正文中包含原子能的对应文章时,我们应该怎么做?

首先,最粗暴的办法,我们可以顺序读取每一篇文章,逐个字符进行判断,如果其中有连续的三个字符是 原子能,我们就记录下来这篇文章的标题,如此全部扫描一遍,我们就完成了一次搜索。

这个方法是相当简单粗暴,且有效的。在计算机性能十分强劲的情况下,对于1G的文件进行搜索,都可以使用这个方法(Linux下的grep命令,经常使用的话应该知道即使在GB级别的文件做些简单的搜索,通常性能也是能接受的)。

但是,数据量会远大于1G,搜索的要求也更加复杂,不是简单的字符串匹配,而是多种条件的组合。此时就需要全文搜索了。

像google这种搜索引擎,可以在0.5s的时间,搜索到与"全文搜索引擎"相关的1230w结果,这显然使用的不是顺序的逐个字符对比,而是类似于lucene的全文搜索了。

lucene能做到在秒级对大量数据进行查询,依赖的就是被称之为索引的结构。对于索引的理解,有很多现成的例子,比如在很多书籍后,都会提供一个关键词到页码的映射,这就是一种索引,可以让我们不用通读整本书,就能找到自己关心的部分。

在《数学之美》这本书中,作者认为全文检索的本质就是布尔代数。随着对全文检索的逐渐深入了解,越来越觉得这句话的精准,在全文检索的索引/搜索阶段,根本原理就是最简单的布尔代数,剩下的只是工程实现的复杂度问题了。

lucene-beta

lucene 目前已经在开发9.0版本了,整个工程分为多个模块,十分复杂。

在学习lucene源码之前,我一直在想,应该以什么路线去学习lucene,总不能随机找一个类开始看吧,那样怕是会陷入细节的汪洋大海中。

最初的想法是,从构建索引开始,走构建索引->写入磁盘->搜索请求->query分析->相关性打分->返回结果这条路线,逐步学习。

后来突然产生了一个大胆的想法,我想尝试抽象全文检索的本质,写一个各方面都最简单的全文检索工具(最好只有一两个类的那么简单),之后就这个工具的各个方面如何进化成lucene的对应模块,各种缺陷lucene是如何改进的, 来进行lucene的学习。

这就是这节的标题lucene-beta的来源。

在我的预期中,这样做应该会有两个优点:

1.能够更加贴近本质,不至于在局部的细节中迷失。

2.从问题推向结论,更加符合情理。能够更加深刻的感受到如此这般的必要性。如无必要,那么单纯炫技又有什么意思呢?

public class LuceneBeta {

    private static final Logger logger = LoggerFactory.getLogger(LuceneBeta.class);


    public static void main(String[] args) {

        LuceneBeta beta = new LuceneBeta();

        String[] arr = new String[]{"原子能研究所", "原子弹威力很大"};

        Map<Character, int[]> index = beta.build(arr);

        int[] searchRet = beta.search('威', index);

        System.out.println(Arrays.toString(searchRet));

    }


    /**

     * 对传入的字符串数组进行字符级别的构建索引

     */

    public Map<Character, int[]> build(String[] arr) {

        Set<Character> all = new HashSet<>();

        for (String s : arr) {

            for (char c : s.toCharArray()) {

                all.add(c);

            }

        }

        Map<Character, int[]> index = new HashMap<>();


        for (Character c : all) {

            int[] perContains = new int[arr.length];

            for (int w = 0; w < arr.length; w++) {

                if (arr[w].contains(String.valueOf(c))) {

                    perContains[w] = 1;

                } else {

                    perContains[w] = 0;

                }

            }

            index.put(c, perContains);

        }


        logger.info("build {} strings. indexed: ", arr.length);

        for (Map.Entry<Character, int[]> e : index.entrySet()) {

            logger.info("{} ==> {}", e.getKey(), Arrays.toString(e.getValue()));

        }

        return index;

    }



    /**

     * 查询目标字符都在哪些字符串中出现过

     */

    public int[] search(char target, Map<Character, int[]> index) {

        if (!index.containsKey(target)) {

            return null;

        }

        int[] ints = index.get(target);

        int[] tmp = new int[index.size()];

        int j = 0;

        for (int i = 0; i < ints.length; i++) {

            if (ints[i] == 1) {

                tmp[j] = i;

                j++;

            }

        }

        int[] ret = new int[j];

        System.arraycopy(tmp, 0, ret, 0, j);

        return ret;

    }


}

说要简单,那就要简单到底,全部代码70行。它实现了什么功能呢?

在给定的一系列字符串中,可以搜索某个字符出现的所有字符串编号

google可以根据你给的关键字找到对应的网页, 上面的代码可以根据你提供的关键字符,查找对应的字符串, 源码已经开发了,就等融资上市了,我就是下一个google...

虽然上面的代码极其简单,但是为了后续对应lucene的分析,我还是要认真的归纳其中的每一个步骤。

上面的程序中,分为两个部分,即两个方法build 和 search.

首先是build过程:

1.遍历输入的字符串,拿到所有出现的字符。

2.对于每一个字符,统计一个字符数组,其中每一位代表当前字符在该编号的字符串中是否出现。1代表出现,0代表未出现。 如"原"在输入的两个字符串中均有出现,那么它对应的统计数组就是[1,1].

3.将所有的字符及其统计数组,作为一份"索引"返回。

search过程

1.如果输入的字符不存在,直接返回空

2.取出对应该字符的统计数组,由二进制的表示办法,还原成原始的字符串编号。

3.返回所有出现该字符的字符串编号。

lucene源码架构介绍

lucene 作为一个成熟的开源软件,其包括了多个模块,其中最核心的是lucene.core包。其中又分为以下几个目录:

attachments-2023-07-mPfEJ6yP64a8bdf2bdabc.jpg

其中:

• org.apache.lucene.analysis 主要负责词法分析及语言处理.

• org.apache.lucene.codecs 主要负责文本内容到倒排索引的编码和解码.

• org.apache.lucene.document 提供了对用户内容的抽象Document,及Fields.

• org.apache.lucene.index 主要负责对索引的读写。

• org.apache.lucene.search 主要负责搜索过程。

• org.apache.lucene.store 主要负责索引的持久化等内容。

• org.apache.lucene.util 工具包。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

想高效系统的学习Java编程语言,推荐大家关注一个微信公众号:Java圈子。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Java入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2023-03-2AoKIjPQ64014b4ad30a3.jpg

  • 发表于 2023-07-08 09:40
  • 阅读 ( 198 )
  • 分类:Java开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章