查询集合组件
查询集合组件(DbQueryList)用于分页查询实体对象的数据列表。
概述
查询集合是最常用的查询组件,按条件筛选目标实体的记录并返回列表,支持选择返回字段、排序规则,以及大数据量查询。它常作为报表数据源、列表页数据来源或后续组件的输入。
查询条件使用统一的「基础 / 高级」编辑模式(详见 全局属性),默认条件过滤掉已删除数据。
配置项
| 配置项 | 说明 |
|---|---|
| 操作对象 | 要查询的实体对象,必填 |
| 默认条件 | 查 询的默认筛选条件,支持基础模式与高级模式 |
| 排序 | 结果的默认排序规则 |
| 查询字段 | 需要返回的字段,可多选,支持关联(lookup)字段 |
| 大数据量查询 | 开启后按大数据量方式分页查询 |
| 导出选择字段模板 | 导出场景下使用的视图模板,可选 |
| 输出到最终结果 | 开启后该组件结果作为接口返回值 |
默认条件
默认条件通过分栏切换「基础 / 高级」两种模式:
| 模式 | 值(ConditionMode) | 说明 |
|---|---|---|
| 基础 | basic | 界面逐项配置,单层「并且 / 或者」 |
| 高级 | advanced | 直接编辑条件 JSON,支持嵌套 |
组件默认条件模板为过滤未删除数据:
{
"Field": "isdeleted",
"Operator": "eq",
"Value": false
}
说明:默认条件模板中的操作符写作
eq,与 查询操作符 中的枚举Eq一一对应(大小写不同表示形式)。
条件值支持服务端占位符,例如 {Env.LoginUserId} 会在执行时替换为当前登录用户 ID;在「对象详情页」调用场景下还支持 {Model._id}、{Model.id}、{Env.id} 等。详见后文「服务端执行逻辑 → 查询条件组装」。
查询字段
「查询字段」决定返回结果包含哪些字段。留空时的取值优先级为:接口请求传入的列(导出场景)→ 当前对象视图的列 表列(metaViewId,所见即所得,并自动附加 workflowdataid)。字段名包含 ~ 的关联字段会自动补上其基础字段。
排序
「排序」为字典结构(字段编码 → 方向),-1 为倒序、1 为正序。留空时默认按 modifiedtime 倒序。排序字段若不在对象字段集合中会被自动移除。
大数据量查询
开启「大数据量查询」后组件以适合大数据量的方式执行查询:单次取数上限提升,并在异步任务中按批分页执行,避免一次性加载全部数据造成压力。
使用场景
- 报表数据源
- 列表页数据加载
- 数据导出前的取数
- 后续组件的输入数据集合
下一步
属性明细
以下内容面向技术实现与 AI 检索,说明查询集合组件的节点元数据。
节点元数据
查询集合组件由 FlowCmpType.DbQueryList 标识。所有节点 meta 值均以字符串存储(布尔、数字、数组等在元数据中同样以字符串形式保存)。
| 属性名 | 类型 | 含义 | 取值/存储值 |
|---|---|---|---|
type | string | 组件类型 | 固定为 "DbQueryList" |
MetaObjectId | string(GUID) | 目标实体对象 | 缺省取当前接口所属对象 |
DefaultFilter | string(JSON) | 高级模式的默认条件 | 条件 JSON,缺省为 isdeleted = false 模板 |
BasicFilter | string(JSON) | 基础模式的默认条件 | 条件 JSON,缺省为系统默认基础条件 |
ConditionMode | string | 条件编辑模式 | "basic"(缺省)/ "advanced" |
Sort | string(JSON) | 排序规则 | 排序字典 JSON,例 "{\"modifiedtime\":-1}" |
QueryFields | string | 查询 字段编码列表 | 逗号分隔,例 "Name,Code" |
QueryHugeData | string(bool) | 是否大数据量查询 | "true" / "false" |
ExportTemplateMetaViewId | string(GUID) | 导出选择字段模板 | 视图(MetaView)主键 |
IsFinalResult | string(bool) | 是否输出到最终结果 | "true" / "false" |
IsDisabled | string(bool) | 是否禁用该节点 | "true" / "false" |
order | string | 同级排序 | 例:"7" |
元数据存储示例
{
"ID": "query1",
"type": "DbQueryList",
"MetaObjectId": "3f9c0b2e-2d3a-4e6f-9c11-0f7a5b8d2e10",
"ConditionMode": "basic",
"BasicFilter": "{\"Logic\":\"And\",\"Filters\":[{\"Field\":\"isdeleted\",\"Operator\":\"eq\",\"Value\":false}]}",
"DefaultFilter": "{\"Field\":\"isdeleted\",\"Operator\":\"eq\",\"Value\":false}",
"Sort": "{\"modifiedtime\":-1}",
"QueryFields": "Name,Code",
"QueryHugeData": "false",
"IsFinalResult": "true",
"order": "7"
}
视图数据源
「导出选择字段模板」下拉通过 POST /api/DataSource/GetMetaViewDataSource 获取,随操作对象切换重新请求。
服务端执行逻辑
本节说明 DbQueryListComponentManager 在服务端的真实执行过程,便于排查与理解组件行为。组件继承自 TriggerComponentManagerBase,接口链路与实体触发器链路均会执行;实体触发器链路额外记录节点级执行耗时。
执行时机与场景
- 执行入口为
_ExecuteAsync,执行结束后沿逻辑图调用ExecuteNextAsync继续下游节点。 - 执行前基类会读取
IsDisabled,为"true"时跳过本组件直接执行下游。 - 导出选择字段特例:当请求 query 参数包含
customExportFields时,组件不查询数据,直接返回可导出字段列表(ResponseResult<List<MetaField>>赋给context.Result)。若配置了ExportTemplateMetaViewId则按该视图模板取列,否则取对象全部字段(含 lookup)。
查询条件组装
查询条件的组装优先级自高到低如下:
context.FilterOverride(最高优先):一旦赋值,覆盖其他所有条件(主要用于触发器重新编辑条件场景),此时不再读取请求条件、默认条件与AndFilter。request.Condition:请求体传入的条件,作为基础条件。- 默认条件:由
ConditionFilterResolver.ResolveAsync(ConditionMode, DefaultFilter, BasicFilter, ctx)解析得到,附加在基础条件之上。ConditionMode为"basic"(去空格、忽略大小写)时读取BasicFilter,按ConditionConfig解析每一行,并按ValueSetType解析值(Direct直接取值;Razor编译模板,注入Env(如Env.LoginUserId、Env.CurrentDateTime)、Query、Trigger.Before/After变量,再按ValueType强制转换)。- 其他 情况(含历史数据的默认值)按「高级模式」把
DefaultFilter原始 JSON 反序列化为DynamicFilter。 - 基础模式与高级模式各自存储(
BasicFilter/DefaultFilter),切换模式不会互相覆盖;缺字段的行会被丢弃。
- 默认值占位符替换:对「基础条件 + 默认条件」合并后的 JSON 字符串做文本替换:
{Env.LoginUserId}→ 当前登录用户 ID(始终替换)。- 需 query 同时存在
metaPageId与dataId:{Model._id}、{Model.id}、{Env.id}→dataId。 - 需 query 存在
detailMetaObjectId:若条件中出现{Model.或{Env.,按detailMetaObjectId读取对象、按dataId读取数据,将{Model.<字段>}/{Env.<字段>}替换为该字段的存储值。 - 注意:占位符替换在拼接
AndFilter之前执行,因此context.AndFilter中的占位符不会被替换。
context.AndFilter:链路按需插入的额外 AND 条件。
权限过滤
- 查询操作权限:除非
SkipOperationPermission生效,否则调用HasPermissionAsync(Query)校验MetaObjectDataOperationType.Query。SkipOperationPermission取自节点meta或context.DicParam,任一为"true"即跳过。- 无查询权限时:将 filter 置为
CommonConst.NotExistFilter(等价_id = 74eb3e0a-416e-4faf-82bc-7e37effff4b1,一个不存在的主键),并跳过后续 MOU 过滤,记录告警日志(结果为空)。
- MOU(数据)权限:除非
SkipMouPermission生效,且上一步未因无操作权限被短路,则通过CombineDataPermissionFilterAsync(context, metaObject, filter, MouPermissionStageEnum.Query)把 MOU 过滤条件以 AND 方式拼接。SkipMouPermission仅从context.DicParam读取。- MOU 过滤来源:优先
context.MouFilter(自定义脚本),否则按对象Properties.MouEnabledForQuery/MouTypeForQuery等配置生成(如「本人创建」「本人所在组织」「某人员字段等于当前用户」等)。
查询字段与排序
查询字段(列)解析优先级:
- 节点
QueryFields(非空即用)。 - 否则若
request.Columns有值(导出场景):取请求列,并把code|name拼接写入context.DicParam["ChameleonExportColumns"]。 - 否则若 query 存在
metaViewId:取该视图ListItems的字段编码,并拼接workflowdataid(用于渲染流程组件,所见即所得)。
随后:含 ~ 的 lookup 字段会补上其前缀基础字段;若最终有字段集合,则与对象字段编码取交集;最后始终追加 _id。
排序解析优先级:
request.Sort(请求体传入,非空即用)。- 否则节点
Sort(JSON 反序列化为Dictionary<string, int>)。 - 否则默认
{ "modifiedtime": -1 }。
之后移除不在对象字段集合中的排序键;大数据量分页时追加 _id 升序作为稳定分页的兜底排序。
执行与 SQL 形态
- 判断是否跨对象(lookup)查询:递归检查 filter 中是否存在含
~的字段。 - 计数:
- 非跨对象:
chameleonDbContext.GetCountAsync(metaObject.Code, filter)。 - 跨对象:
sqlManager.GetLookupQueryCountSql(...)生成 SQL,用chameleonDbContext.ExecuteScalarAsync(sql, param)执行。
- 非跨对象:
- 取列表:
- 非跨对象:
chameleonDbContext.GetListAsync(metaObject.Code, filter, columns, sort, skip, pageSize)。 - 跨对象:
sqlManager.GetLookupQueryListSql(...)生成 SQL,用chameleonDbContext.GetListBySqlAsync(sql, param)执行。
- 非跨对象:
- 大数据量分页分支:当
context.TinyTaskContext != null且QueryHugeData="true"时,按BatchOperationThreshold(100)为页大小逐页查询并累加,每页调用TinyTaskContext.UpdateProgress(page, totalPages)上报进度;否则单次按request.Skip/request.PageSize查询。
数据翻译
每批结果都会执行两步翻译:
dataSourceApp.TranslateAsync(result, metaObject._id, metaFields):把存储值转换为展示值(多语言、数据源等)。dataSourceApp.TranslateLookupAsync(result, metaFields, queryFields):按查询字段填充 lookup(关联)字段的展示内容。
输出与上下文
| 输出项 | 内容 |
|---|---|
context.CmpResult | List<ObjectData> 结果集 |
context.DicParam["BizDataIds"] | 结果前 100 条的 _id,逗号拼接 |
context.DicParam["MetaObjectCode"] | 对象编码 |
context.DicParam["MetaObjectId"] | 对象 ID |
context.DicParam["ChameleonExportColumns"] | 导出场景下的 code|name 列信息 |
当 IsFinalResult="true" 时,组件把结果写入 context.TransferResult.List / .Total,并赋值 context.Result = ResponseResult<List<ObjectData>>.Success(list).Total(count) 作为接口最终返回值。