1. 方案概述
本文旨在设计全文搜索功能,包括数据的存储、数据权限、数据接口、数据模型等,从整体设计全文检索方案。
2. 解决方案
全文搜索解决方案主要包含两部分,数据的存储及数据的查询展示,其中数据存储方面,主要分为业务数据存储及附件存储;而数据查询展示主要是根据关键字及权限进行查询展示。
2.1. 全文检索接
1 @RequestMapping("/es") 2 @Api(value = "ES服务", tags = { "ES服务" }) 3 public interface IElasticsearchService { 4 5 @PostMapping("/save") 6 @ApiOperation(value="ES文件存入ES库,包括ES的更新") 7 public ESInfoVO save(@RequestBody ESInfoVO esInfoVO); 8 9 @SuppressWarnings("rawtypes") 10 @PostMapping("/batch-save") 11 @ApiOperation(value="ES文件存入ES库") 12 public Result save(@RequestBody List<ESInfoVO> esInfoVOs); 13 14 @SuppressWarnings("rawtypes") 15 @PostMapping("/delete") 16 @ApiOperation(value="删除ES文件") 17 Result delete(@RequestBody ESInfoVO esInfoVO); 18 19 @PostMapping("/find") 20 @ApiOperation(value="多条件查询") 21 public PageVo search(@RequestBody ESInfoRequestVO eSInfoRequestVO); 22 }
2.2. 全文检索模型
2.2.1. 数据存储模型
字段名称 |
字段含义 |
字段类型 |
是否创建索引 |
备注 |
esId |
物理主键 |
String |
是 |
如果无附件,则为业务ID,如果是有附件,则为附件ID |
businessId |
业务主键 |
String |
是 |
业务主键ID |
businessType |
业务类型 |
String |
否 |
业务类型:发文:dispatch 收文:receipt 知识:knowledge 信息:information 法规:statute 档案:archives |
authUserIds |
权限用户 |
String |
否 |
ID,中间采用英文逗号隔开 |
businessTopic |
业务主题 |
String |
是 |
业务标题 |
businessContent |
业务正文 |
String |
是 |
业务正文 |
attachId |
附件ID |
String |
是 |
附件ID |
attachContent |
附件内容 |
String |
是 |
附件内容 |
attachName |
附件名称 |
String |
是 |
附件名称 |
attachPath |
附件路径 |
String |
是 |
附件路径:从附件表获取的 |
ext1 |
扩展字段1 |
String |
是 |
|
ext2 |
扩展字段2 |
String |
是 |
|
ext3 |
扩展字段3 |
String |
是 |
|
ext4 |
扩展字段4 |
String |
是 |
|
ext5 |
扩展字段5 |
String |
是 |
|
ext6 |
扩展字段6 |
String |
是 |
|
2.2.2. 数据检索模型
字段名称 |
字段含义 |
字段类型 |
是否必传 |
备注 |
keyWord |
检索关键字 |
String |
是 |
检索关键字 |
currentUser |
检索用户 |
String |
否 |
|
moduleType |
业务类型 |
String |
是 |
业务类型:发文:dispatch 收文:receipt 知识:knowledge 信息:information 法规:statute 档案:archives |
pageSize |
分页大小 |
int |
否 |
默认20 |
pageNum |
查询页码 |
int |
否 |
默认0 |
2.2.3. 关键模型说明
esId:ES主键,与实际业务有关联,建议:如果无附件,则为业务ID,如果是有附件,则为附件ID。备注:一个ID可能关联多个附件,因此,建议有业务的附件的情况下,主键采用附件ID。
businessId与businessType:组合可以关联到实际的业务页面。
authUserIds:授权ID,也就是有权访问用户就集合,中间用英文逗号“,”隔开。
attachPath:附件路径,该值是判断是否解析附件的依据,该附件存在于附件服务器(非影像平台)。
keyword:检索的关键字,可以是正文、主题、附件名称、附件内容等。
moduleType:检索的分类,分为:发文:dispatch、收文:receipt、知识:knowledge、信息:information、法规:statute、档案:archives。
2.3. 关键技术设计
2.3.1. 数据权限设计
针对数据权限控制,一般有三种方案:
方案一:权限单独存储,先条件检索,后过滤权限;
方案二:权限单独存储,先权限过滤,后进行检索;
方案三:权限冗余到ES中,直接进行检索过滤;
针对三种不同的方案,实现方式不同,下面我们将针对三种方案进行优劣分析,然后进行数据权限控制设计。
2.3.1.1. 方案一:权限单独存储,先条件检索,后过滤权限
业务流程:
- 发送请求,点击检索;
- 到ES检索数据(不考虑权限);
- 将检索结果存入DB的临时表中;
- 权限表与临时表联合查询(权限过滤);
- 将结果返回到检索结果页面进行渲染;
- 用户点击具体结果条目,根据业务ID和业务条目到业务不要进行检索;
- 将查询结果,显示到业务页面。
方案特点:
- 核心查询分3步:ES查询、结果存储、关联查询;
- 全文检索涉及DB与ES两个库;
- 多并发操作,数据量较大,业务逻辑复杂。
2.3.1.2. 方案二:权限单独存储,先权限过滤,后进行检索
业务流程:
- 发送请求,点击检索;
- 到DB中查询权限数据,获取业务ID;
- 将业务ID作为过滤条件;
- 根据关键字、分类及业务ID进行检索;
- 将结果返回到检索结果页面进行渲染;
- 用户点击具体结果条目,根据业务ID和业务条目到业务不要进行检索;
- 将查询结果,显示到业务页面。
方案特点:
- 核心查询分2步:DB查询、ES查询;
- 全文检索涉及DB与ES两个库;
- 多并发操作,数据量较大,查询费资源(内存、CPU、IO);
- 业务逻辑复杂。
2.3.1.3. 方案三:权限冗余到ES中,直接进行检索过滤
业务流程:
- 发送请求,点击检索;
- 根据检索条件到ES进行检索(权限就是检索条件之一);
- 将结果返回到检索结果页面进行渲染;
- 用户点击具体结果条目,根据业务ID和业务条目到业务不要进行检索;
- 将查询结果,显示到业务页面。
方案特点:
- 核心查询分1步:ES查询;
- 全文检索只涉及ES库;
- 数据抽取时,需要将权限在ES中冗余。
因此,全文检索的数据权限,采用方案三:权限冗余到数据中,直接进行检索过滤。
2.3.2. 数据操作设计
模型数据操作采用spring-data-elasticsearch,对于数据的新增、修改、删除直接使用ElasticsearchRepository提供的增删该接口即可。对于查询,由于要对好像结果进行高亮处理,不能直接使用ElasticsearchRepository提供的接口,而需要使用spring-data-elasticsearch提供的QueryBuilder、NativeSearchQuery以及ElasticsearchTemplate三个组合实现。
关键点说明:
保存:直接调用save方法即可;
更新:直接调用save方法即可;注意:只要主键esId与原先保持一致,即可进行更新;
删除:直接调用delete方法即可;
查询:QueryBuilder进行查询条件拼装;NativeSearchQuery进行关键字高亮设置;ElasticsearchTemplate根据查询条件及关键字设置进行查询并返回结果。
2.3.3. 附件解析设计
附件涉及的文件类型太多,无法一一提供,本解决方案重点在于常见附件类型,如:doc、docx、pdf、pdfx、wps,这几种附件的解析。
doc/wps解析:采用WordExtractor进行数据抽取;
docx解析:采用XWPFWordExtractor进行数据抽取;
pdf/pdfx解析:采用PDFTextStripper进行数据抽取;