1 背景
Nested类型字段是一对多关联对象搜索的解决方案,动态扩展字段在业务系统很常见,搜索引擎需要支持,本文介绍onesearch组件如何使用nested,使用nested实现索引和查询动态扩展索引属性
2 参考资料
《搜索引擎onesearch 1.0-设计与实现.docx》
《搜索引擎onesearch 2.0-设计与实现.docx》
《分布式dataX详细(落地)设计》
1 术语
Ø 文档 Document
elasticsearch 一行数据称为文档,需要注意与文件/文档区分,有冲突的地方用“ES文档”区分
Ø 索引schema
相当于关系数据库的schema,xml格式,定义索引的字段,类型,还有搜索策略,分词等搜索相关属性
Ø 搜索/过滤
elasticsearch查询分两部分,搜索和过滤,搜索计算文档与搜索词相似(匹配)度,得出分数排序,分数越高相似度越高,排序也靠前;过滤相当于sql的where,结果是true或者false
Ø 分词
索引可以设定是否分词,分词,分词器分割文本或字符串成term,适用模糊搜索;反之,使用term查询
Ø 查询对象装配映射
elasticsearch es dsl 查询功能非常丰富,可调参数多, 提供精准细致的搜索调整,但也很难用,更难复用,onesearch设计装配映射组件支持通用表达式转换esdsl,用户只需编写通用表达式,如,((f1=‘a’or f2=’b’) and f3=‘c’)) 即可实现搜索过滤,类似elasticsearch自身也提供了sql查询功能,大大降低开发难度,同时具备高复用性
2 特性
2.1 大规模/分布式文件索引
Ø 文档抓取
1) 文档内容抓取组件,metadata+content
2) 抓取组件隔离机制
Ø 索引引擎,基于分布式setl(批量/增量),reader/writer
2.2 精确搜索/多元搜索
Ø 装配/映射 增加支持query,目前已支持映射为filter
1) full Text查询映射策略
match/match_phrase/query_string
2) 高亮 (已有,未测试)
3) 返回字段,目前全返回
4) 批量操作,引擎层已实现
Ø springboot starter
2.3 智能搜索
Ø 搜索权限,搜出就能看
Ø nested字段/动态扩展索引
suggester,建议补全/建议纠错
3 onesearch总体架构
Ø schema模块,定义索引字段,索引策略,搜索策略等,管理索引及其搜索特性
Ø 聚合搜索(agg)模块,基于schema模块,支持xml定义agg,零编码增加agg主题
Ø 查询模块,负责构建通用表达式(如,((f1=‘a’or f2=’b’) and f3=‘c’)),作为搜索输入条件
Ø 映射引擎,映射通用表达式为最优的es dsl,支持=,!=,like,in,range,prefix,not/and/or,大小括号,点(.)等操作符映射,解决es dsl难使用,难复用的痛点
Ø 抽象搜索引擎接口,无缝接入不同的搜索引擎,如,elasticsearch,opensearch,solrcloud等,更可同时使用多种引擎
Ø 索引同步组件,全量同步/增量同步
Ø 抓取组件,索引数据抓取组件,如,文件内容抓取,数据库抓取
Ø 文档权限,能搜就能看
Ø 扩展属性,用户自定义索引扩展字段
suggester,建议补全/建议纠正
4 Nested字段/动态扩展索引属性
nested类型字段是elasticsearch一种内嵌对象类型(另外还有Object,Join)*,支持数组
动态扩展属性允许用户自定义增加索引属性,并可用于搜索
本节介绍onesearch如何支持nested类型,以及使用nested map实现动态扩展索引属性
*Object对象类型对数据拉平存储,不能实现精准检索匹配,搜出不满足查询结果的数据,才导致 Nested 的出现;Join独立存储,不能一次性与主数据搜索出来
4.1 shema
schema增加nested类型字段
NestedField继承CompoundField,聚合多个PropertyField
Ø nested map/动态索引属性
上图,schema nested字段定义,两个nested字段
下图:对应索引属性和数据,支持动态增加map属性,实现动态索引属性
Ø 对象列表
上图使用相同的schema,path1有两个对象,看着属性不同,实际mapping是一样,赋值字段不一样;索引可以是map,也可以是bean
4.2 索引
nested是主从一对多数据,如文档索引,主数据是文档信息, 扩展属性是从数据
索引使用分布式datax平台,rbt转换组件
4.3 搜索
nested搜索关键是表达式映射,如,non_nested_exp and ((path1.key1== ‘p1k1’ and path1.value1==”p1v1” ) or (path2.key1== “p2k1” and path2.value1==”p2v1”)), path*是nested类型字段
映射模块实现一套nested的操作符映射(OperatorMapping),组件采用延迟处理策略,尽可能合并nested项,不立刻构建nested,等到下一个not/and/or,若不是同一个path或者不是nested,则nested
下面两图展示了3种场景生成的dsl
a 不同path的nested
((path1.key1== ‘p1k1’ and path1.value1==”p1v1” ) or (path2.key1== “p2k1” and path2.value1==”p2v1”))
b 相同path的nested
((path1.key1== ‘p1k1’ and path1.value1==”p1v1” ) or (path1.key2== “p1k2” and path1.value2==”p1v2”))
c 中间非nested
(path1.key1== ‘p1k1’ and path1.value1==”p1v1” ) and xxx==“aaa”
or (path1.key2== “p1k2” and path1.value2==”p1v2”)
场景a
场景b
场景c
5 配置
Nested操作符映射兼容原有,为了兼容现有代码,增加onesearch.nested.enable配置项激活nested映射组件