子文档(sub doc)是引擎提供的子doc功能,主要是为了支持商品搜索中对于商品更细粒度的 SKU 的检索。通过 sub doc 功能,我们既可以进行商品粒度的检索,也可以高效的对商品所属 SKU 进行检索。常见的使用场景是主商品与sku属性的关系,若干个sku对于主商品来讲是多个子doc。
1、配置带有子文档的schema
在配置中心>索引结构中添加一张索引表:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713668.png)
注意:每张索引表都必须对应一个数据源,添加数据源可参考数据源。
在管理员模式下填写索引表、数据源,数据分片,同时配置字段和索引:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713669.png)
打开开发者模式按如下模板填写sub_doc:
"sub_schema":{
"table_name": "sub_simple_table",
"fields": [
{"field_name":"sub_id", "field_type":"INTEGER"},
{"field_name":"sub_body", "field_type":"TEXT", "analyzer":"simple_analyzer"},
{"field_name":"sub_title", "field_type":"TEXT", "analyzer":"simple_analyzer"},
{"field_name":"sub_multi", "field_type":"INTEGER", "multi_value":true }
],
"indexs":
[
{
"index_name": "sub_index",
"index_type" : "EXPACK",
"index_fields":
[
{
"field_name":"sub_body",
"boost":100
},
{
"field_name":"sub_title",
"boost":100
}
]
},
{
"index_name": "sub_pk",
"index_type" : "PRIMARYKEY64",
"index_fields": "sub_id",
"has_primary_key_attribute": true
}
],
"attributes": [
"sub_id", "sub_multi", "sub_int"
]
}
说明:
table_name:子表的表名
子表下包括:fields、indexs、attributes,但是不支持summary;
配置完成后,点击发布:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713671.png)
index发布完成后,在配置中心>高级配置>数据处理配置中编辑对应的数据源的data_tables配置:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713672.png)
点击编辑:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713673.png)
进入data_tables目录后编辑xxx_table.json:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713675.png)
在sub_document_processor_chain中配置sub doc相关配置:
"processor_chain_config": [
{
"sub_document_processor_chain": [
{
"class_name": "OneBuildProcessor",
"module_name": "BuildModule",
"parameters": {
"BuildStep": "BeforeTokenizer",
"DocType": "add,update,delete",
"config_path": "pluginsConf/subdoc_one_build.json"
}
},
{
"class_name": "TokenizeDocumentProcessor",
"module_name": "",
"parameters": {}
},
{
"class_name": "OneBuildProcessor",
"module_name": "BuildModule",
"parameters": {
"BuildStep": "AfterTokenizer",
"DocType": "add,update,delete",
"config_path": "pluginsConf/subdoc_one_build.json"
}
}
],
"document_processor_chain": [
{
"module_name": "BuildModule",
"class_name": "OneBuildProcessor",
"parameters": {
"BuildStep": "BeforeModifyField",
"config_path": "pluginsConf/one_build.json"
}
},
{
"module_name": "",
"class_name": "ModifiedFieldsDocumentProcessor",
"parameters": {
"derivative_relationship": ""
}
},
{
"module_name": "BuildModule",
"class_name": "OneBuildProcessor",
"parameters": {
"BuildStep": "BeforeTokenizer",
"config_path": "pluginsConf/one_build.json"
}
},
{
"class_name": "TokenizeDocumentProcessor"
},
{
"module_name": "BuildModule",
"class_name": "OneBuildProcessor",
"parameters": {
"BuildStep": "AfterTokenizer",
"config_path": "pluginsConf/one_build.json"
}
}
],
"table_name": "${table_name}",
"clusters": [
"${clusters}"
],
"modules": [
{
"module_name": "BuildModule",
"parameters": {},
"module_path": "libPluginOffline.so"
}
]
}
其中${table_name}和${clusters}都需要填入索引名,可在索引结构中查看:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713676.png)
其中配置中的config_path的“pluginsConf/one_build.json”,pluginsConf与xxx_table.json同级是一个目录,目录下需要上传one_build.json和subdoc_one_build.json文件,内容模板如下:
one_build.json:
{
"chains": {
"BeforeTokenizer": [
"Duplicator",
"SplitProcessor"
],
"BeforeModifyField": [],
"AfterTokenizer": []
},
"processors": [
{
"name": "Duplicator",
"class": "Duplicator",
"parameters": {
"dup_fields": "",
"hidden_flag": "true"
}
},
{
"name": "SplitProcessor",
"class": "SplitProcessor",
"parameters": {
"HiddenFlag": "true",
"FieldsAndSeparators": ""
}
}
]
}
subdoc_one_build.json
{
"chains": {
"BeforeTokenizer": [
"Duplicator",
"SplitProcessor"
],
"BeforeModifyField": [],
"AfterTokenizer": []
},
"processors": [
{
"name": "Duplicator",
"class": "Duplicator",
"parameters": {
"dup_fields": "",
"hidden_flag": "true"
}
},
{
"name": "SplitProcessor",
"class": "SplitProcessor",
"parameters": {
"HiddenFlag": "true",
"FieldsAndSeparators": ""
}
}
]
}
配置完成后,在数据处理配置页点击【发布版本】:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713679.png)
发布完成后,会有一个新的配置版本生成:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713680.png)
推送离线配置并索引重建:
此时相关配置已经完成,需要在运维中心>运维管理中通过配置更新推送离线配置并索引重建:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713681.png)
索引重建进度,可在变更历史>数据源变更下查看:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713682.png)
等待手动触发全量的FSM流程结束后,即可在线上访问配置了sub doc的相关索引。
2、配置查询配置
如果需要子文档在查询中使用,还需要在配置中心>高级配置>查询配置中,修改qrs配置:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713686.png)
编辑qrs.json:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713688.png)
在extend_processors 中添加子文档的相关配置:
{
"processor_name": "xxx",
"module_name": "QrsModule",
"parameters": {
"SubDocIdName": "sub_doc_id",
"searcher_schema_path": "schemas/xxx_schema.json",
"SubDocHitField": "xxx",
"SubDocIdCompress": "C",
"primary_key": "xxx"
}
},
添加完成后,在查询配置页面,点击发布:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713692.png)
发布完成后会生成一个新的配置版本:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713695.png)
在运维中心>运维管理页中点击配置更新:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713698.png)
更新在线配置,选择3中生成的查询配置版本,同时选择目标集群,点击确定:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713699.png)
可在运维中心>变更历史页中的集群变更中查看配置生效进度:
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713701.png)
以上FSM流程更新完成后,线上业务即可在查询中使用子文档。
3、子文档的查询方式
sub doc 查询逻辑
在配置中配 sub doc,以及建立好 sub doc 索引之后,我们就可以进行 sub doc 模式下的查询。sub doc 查询是通过 config clause 中的 sub_doc 开关开启的,默认为 'no'。开启有两种方式,'group' 与 'flat'。
sub_doc:no
一切行为与正常查询相同,query 里面可以出现 sub doc 索引的 term,但是命中都是在 doc 级别的,返回的也都是 doc。下面我们介绍这几种模式下 sub doc 查询的行为。
sub_doc:group
query 中若出现 sub doc 索引的 term,则会对在 sub doc 级别上做查询。返回的结果包括命中的 doc 以及其命中的 sub doc,sub doc 下挂在 doc 上,用户插件可以通过 SubSlabAcceesor 的 foreach 接口来访问 sub doc 的属性等,也可以利用 ProcessorWrapper 来封装 accumulation 类的操作,或者利用 virtual_attribute 配合 sub_* 函数将 subdoc 的 attribute 进行处理返回到结果中。下挂的 sub doc 不会序列化到最后结果中。
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713703.png)
sub_doc:flat
与 sub_doc:group 相似,会在 sub doc 上做查询,而返回的结果是按 sub doc 展平的,doc 的结果会被合并到其所属的每个 sub doc 上,也就是说所有的 sub doc 会包含其 doc 的属性,出现在结果中,插件以及结果中出现的实际上是所有的 sub doc,而 doc 不会单独出现在结果中。这种模式下性能比较差。
![image.png](https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/9605643961/p713705.png)
查询行为解读
表达式概念,virtual attribute
表达式中只包含主 doc 上的 attribute 或者 variable 的为主表达式,如果表达式中有 sub doc attribute 或者 sub doc variable 参与了运算,那么这个表达式为子表达式,对应返回的结果(如 attribute 子句中)将在 sub doc 上。在 virtual_attribute,filter,cache_filter 等中,group 模式下不允许出现子表达式,而 flat 模式下可以。
cache
group 模式下 cache_filter 不支持 sub doc attribute。
cache 命中与否与 sub doc 无关,只与 doc 有关。出现 sub doc 被删情况下,同样的 query 会命中 cache,而被删掉的 sub doc 会被过滤掉。
某些 cache 中 doc 上的计算结果用到 sub doc 的属性,而增量时若 sub doc 被删除或者添加,该 doc 上的值不会被重新计算。
查询字句在 sub_doc 下的行为
字句 | sub_doc:no | sub_doc:group | sub_doc:flat | 备注 |
query | 可以出现在 sub schema 索引中的 term,但命中都在 doc 上。 | 可以查询 doc 和 sub doc 的 term,sub doc 将下挂在 doc 上供插件访问,但不会出现在最终序列化结果中。 | 可以查询 doc 和 sub doc 的 term,sub doc 将展开,插件看到的是所有命中的 sub doc,结果中是全部命中 sub doc | 为了实现简单,ANDNOT sub_term 的情况目前实现的并不完全。A ANDNOT B 时如果 B 是一个 sub term,带 B 的主 doc 都会被过滤掉,而不是只带 B 的 sub doc 被过滤掉。 |
pkfilter | 与原有行为相同 | 不支持 | 不支持 | |
filter | 不可以带 sub doc attribute | 可以指定 subdoc attribute 过滤 sub doc | 与 group 模式下行为相同 | 如果一个 doc 中没有满足条件的 subdoc,那么整个 doc 会被过滤掉。 |
aggregate | 同上 | 支持 | 支持 | |
attribute | 同上 | 不支持 | 支持 | |
distinct | 同上 | 不支持 | 支持 | |
sort,rank_sort | 同上 | 不支持 | 支持 | |
layer | 与原有行为相同 | 不支持 | 不支持 | |
fetch_summary | 与原有行为相同 | 不支持 | 不支持 | 下版本可能会支持取 sub doc summary |
注意事项
不支持 sub doc配置 summary,不支持 sub doc 辅表。