9

如何从 0 到 1 搭建代码全局检索系统

 3 years ago
source link: https://www.zoo.team/article/checkcode
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何从 0 到 1 搭建代码全局检索系统

2021-08-03 发布于 方案沉淀 · 阅读量:132

责任小编:心火

目前,前端团队的项目有几百个左右,想要查找某个接口 API 或者某个 NPM 包以及一些关键词在哪些项目中使用到,需要每个开发同学在自己维护的项目里全局搜索一遍或者写个脚本跑一遍,然后统计上去,实际上,这是一个比较耗费人力资源和时间的事情。于是,代码全局检索系统——千寻“应运而生”,其核心借助于 Elasticsearch 强大的全文检索能力。

正文开始之前,先揭开 “千寻“ 神秘的 ”面纱“ ,效果图如下:

qianxun.gif

Elasticsearch 是什么?

Elasticsearch ,简称 ES,是一个分布式可拓展的实时搜索和分析引擎,它的底层是开源库 Apache Lucene,也就是说 ElasticLucene 的二次封装。如果你想访问 Elasticsearch,可以直接使用 HTTP 的 RestFul API 方式,来增删改查。说到增删改查,我们很容易想到关系型数据库。

这里,有一份简单的术语对照表:

关系型数据库 数据库 表 行 列 Elasticsearch 索引(Index) 类型(Type) 文档(Document) 字段(Fields)

即,Elasticsearch 的索引、类型、文档、字段分别类比关系型数据库的数据库、表、行、列。

看完之后,是不是对 Elasticsearch 有了初步的概念。为了不损耗大家的脑细胞,点到为止,有感兴趣的小伙伴,可以去查阅相关资料,深入了解( Elasticsearch7.6中文文档 )。

整体设计架构

qianxun.png

Node-server

主服务,负责执行 Node-fscrawler 脚手架相关命令,以及对外提供项目录入、查询等能力。

GitLab

通过调用 GitLab API,来获取或下载项目。这里推荐一个插件 gitbeaker,对 GitLab API 做了二次封装,用起来还是蛮香的。分页获取有权限的项目列表,如下图所示:

gitbeaker.png

Node-fscrawler

下载并爬取项目文件,然后生成一份 JSON 文件,最后通过调用 Elasticsearch API ,实现项目文件导入到 ES。

Elasticsearch

全文检索服务,提供代码全局检索能力。目前用的版本是 7.9.3,这里用了第三方 Elasticsearch 的 Node 版的一个包,elasticsearch.js 上手十分轻松,只需几行代码,就可以玩转 Elasticsearch ^ _ ^

es client.png

Mysql

持久化存储项目信息、项目文件内容、搜索数据统计等等。

项目信息录入

将项目相关信息存储到 MYSQL数据库,这里有四种录入方式,项目名称项目 ID项目组名称项目组 ID,其中 项目名称项目 ID 针对单个项目的录入,当需要录入某个组下的所有项目时可使用传入项目组名称项目 ID。最后,可选择需要录入的项目手动录入。

项目信息录入.png

效果图如下:

项目信息录入.gif

项目文件同步到 ES

同步分为单项同步批量同步批量同步其实就是递归多个项目然后执行单项同步的操作。首先,发起同步请求,主服务会执行脚手架命令 fscrawler syncES <projectName> ,如果本地根目录下( .node-fscrawler 默认根目录)没有找到该项目名称的目录,会先下载并解压该项目到默认根目录下,然后根据生成特地结构数据的 JSON 文件,最后读取该 JSON 文件数据并调用 Elasticsearch Bulk API 批量导入到 ES。

核心代码如下:

crawProjectsBluk.png

代码全局检索

至此,项目文件的数据已经导入到 ES 了,那么,接下来最重要的就是关键词搜索并呈现出结果。搜索页面主要信息有:项目名称、搜索结果、项目描述、项目负责人等,点击项目名称和搜索结果会跳转到对应的 GitLab 仓库的项目和文件页面。由于项目文件内容基本都是英文,则采用 Standard 分词器,如果你想对中文分词,可以推荐使用 IK 分词器。

核心代码如下:

query.png

主服务消息中心设计

一些异步任务和操作,比如:文件异步下载、开启子进程等,可以放到消息中心这个模块,主要是为了降低耦合度,解耦控制器层。

借助 inversifyEventEmitter

  • inversify

    InversityJS 是一个 IoC 框架。IoC ( Inversion of Control ) 包括依赖注入 ( Dependency Injection ) 和依赖查询( Dependency Lookup )。相比于类继承的方式,控制反转解耦了父类和子类的联系。

  • EventEmitter

    Node.js 的内置核心模块,本质上就是观察者模式的实现。这里只用了 emit、on 这两个 API,通过 emit 注册一个事件名并传入参数,然后 on 监听这个事件名并执行回掉函数。

初始化容器

container.png

初始化消息中心插件,并绑定到容器

initPlugins.png

ExecNodeFscrawler 类功能,主要是监听 syncES 事件,通过 spawn 开启子进程,执行脚手架命令

ExecNodeFscrawler2.png

控制器层,依赖注入该消息中心插件,触发 syncES 事件

ExecNodeFscrawler3.png

上千个项目文件如何导入到 ES?

bulk 批量导入数据,批量导入可以合并多个操作,如:Index(创建)、Update(更新)、Delete(删除)。

Bulk API 如下:

bulk API.png

node-fscrawler 脚手架,会项目的所有文件生成一个 JSON 文件,然后调用 client.bulk 方法,将数据一次性导入到 ES。

JSON 文件数据格式如下:

JSON.png

未来,展望

“千寻”,设计初心是为了提高代码全局检索效率,降低人力成本。未来,“千寻”还会进一步提升检索命中率,支持精确搜索,实现项目文件实时同步至 ES 等等。

❉ 作者介绍 ❉
%E6%A2%93%E5%AE%89.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK