文档检索(search project)

介绍:日常pc使用或者app使用或者可供开发者参考的文档都会用到的一个常见的功能就是搜索,此项目就是如何去实现一个简单的搜索引擎。
技术要点:spring boot、mybatis、mysql
主要实现的模块包括四个:文档的准备(这里下载了一个文档到本地),构建索引,索引保存,搜索模块。

文档准备

1.这里常规的情况下应该是通过网络爬虫或者把用户提交过来的信息存成一个文档实时动态更新,但这里用的是本地下载的文档。

构建索引以及索引保存

正排索引: 由文档指向关键词。倒排索引: 由关键词指向文档。
项目中只针对html文档进行搜索,刚开始将文档以文件的形式进行存储,但查看打开文件的时候卡顿严重,在indexer目录下。
流程:
1.扫描文档目录的所有文档
通过FileScanner工具类对本地进行扫描得到文件列表
2.得到所需信息比如文档标题,最终url以及文档内容
根据文件列表构建文档列表,这里针对每个 html 文件,得到其 标题、URL、正文信息,把这些信息封装成一个对象(文档 Document)
3.构建索引
正排索引正常尾插,倒排索引对文档进行了分词操作(引入第三方分词工具),正排索引是一个IndexDocument类型的集合,倒排索引是一个map,key中存的是词,value就是一个DocWeight的集合,docweight包含的信息就是词,文档id和权重(这就是倒排的表现)

分词

调用工具类(Toanalysis)根据标题title分词得到一个list,然后根据list统计标题中词出现的次数用map来统计key是string,value是Integer,同理对正文进行分词计算词出现的次数,然后统计标题文章的词进行权重的计算,这里标题中的词*10正文中的词按原值进行计算.
4.保存索引信息
以json的格式存进去

// forward.json
        File forwardFile = new File(properties.getIndexRootPath(), "forward.json");
        objectMapper.writeValue(forwardFile, forwardIndex);
        log.debug("正排索引已保存。{}", forwardFile.getCanonicalPath());

        // inverted.json
        File invertedFile = new File(properties.getIndexRootPath(), "inverted.json");
        objectMapper.writeValue(invertedFile, invertedIndex);
        log.debug("倒排索引已保存。{}", invertedFile.getCanonicalPath());

构建完成发现查看文件困难,决定保存成表记录。
正排索引表大概1W条数据,一次插入10条数据,倒排索引表虽然大部分都是词id什么的但是整体量级较大,到了百万级别,决定每次插入1W条。
正排索引之前的文章id是由尾插递增生成的,在数据库中可自增生成,把保存索引数据的过程变成批量插入,用到了mybatis。

搜索

访问接口要求进行传参,就是你想要查询的文字信息要手动传入
1.前端传词
2.根据拿到的词在正排索引表和倒排索引表查找拿到一个包含传入参数信息的结果集,这里值得一提的是多词搜索的时候如何给出文档的列表。
大体思路是这样的:
比如查三个词,会得出来三个结果集。每个结果集的docid是有可能重复的,把相同的docid的权重进行聚合然后进行重排序,但是这样对多词搜索的处理虽然有变化,但是查询的一个结果并不是特别的符合预期,也就是对于查询这一块通过一些策略肯定可以更好的进行查询具体代码如下

// 针对所有文档列表,做权重聚合工作
        // 维护:
        // docId -> document 的 map
        Map<Integer, DocumentWithWeight> documentMap = new HashMap<>();
        for (DocumentWithWeight documentWithWeight : totalList) {
            int docId = documentWithWeight.getDocId();
            if (documentMap.containsKey(docId)) {
                DocumentWithWeight item = documentMap.get(docId);
                item.weight += documentWithWeight.weight;
                continue;
            }

            DocumentWithWeight item = new DocumentWithWeight(documentWithWeight);
            documentMap.put(docId, item);
        }

        Collection<DocumentWithWeight> values = documentMap.values();
        // Collection 没有排序这个概念(只有线性结构才有排序的概念),所以我们需要一个 List
        List<DocumentWithWeight> list = new ArrayList<>(values);

        // 按照 weight 的从大到小排序了
        Collections.sort(list, (item1, item2) -> {
            return item2.weight - item1.weight;
        });

3.结果集完成之后去构建一个显示的描述,类似于百度中你查一个词,出来的条目文章下面会有一些简单信息的展示,这里构建的描述就是拿到词的索引,他前面截取一些词,后面截取一些词当做描述,然后写进document的desc属性,这样从前端进行获取的时候,描述信息就有了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Elasticsearch是一个开源的分布式搜索和分析引擎,可以通过检索关键字来查找相关文档。它是基于Java编写的,具有高度可伸缩性和容错能力。 在Elasticsearch中,我们可以通过创建一个索引来存储和组织文档。索引是类似于数据库中的表的概念,它包含多个文档,每个文档又包含多个字段。每个字段都有一个特定的数据类型,如文本、数字或日期。 当需要检索关键字时,我们可以使用查询API来执行搜索操作。查询API提供了多种查询类型,如精确匹配、模糊查询、范围查询等。我们可以指定要搜索的字段和要匹配的关键字,Elasticsearch将返回与关键字匹配的文档。 在搜索过程中,Elasticsearch会使用倒排索引来加速搜索速度。倒排索引是一种反向索引的数据结构,它将每个关键字映射到包含该关键字的文档列表。这样,当我们搜索关键字时,Elasticsearch只需要查找包含该关键字的文档,而不是遍历整个文档集合。 除了基本的关键字搜索外,Elasticsearch还提供了更高级的功能。例如,它支持全文搜索,可以将搜索关键字分词后匹配文档中的词项。它还支持聚合操作,可以对搜索结果进行统计、分组和计算等操作。 总的来说,通过使用Elasticsearch检索关键字功能,我们可以快速准确地找到与关键字相关的文档。它在大数据场景下具有很高的性能和灵活性,被广泛应用于各种搜索和分析场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值