Skip to main content

查询集合组件

查询集合组件(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 值均以字符串存储(布尔、数字、数组等在元数据中同样以字符串形式保存)。

属性名类型含义取值/存储值
typestring组件类型固定为 "DbQueryList"
MetaObjectIdstring(GUID)目标实体对象缺省取当前接口所属对象
DefaultFilterstring(JSON)高级模式的默认条件条件 JSON,缺省为 isdeleted = false 模板
BasicFilterstring(JSON)基础模式的默认条件条件 JSON,缺省为系统默认基础条件
ConditionModestring条件编辑模式"basic"(缺省)/ "advanced"
Sortstring(JSON)排序规则排序字典 JSON,例 "{\"modifiedtime\":-1}"
QueryFieldsstring查询字段编码列表逗号分隔,例 "Name,Code"
QueryHugeDatastring(bool)是否大数据量查询"true" / "false"
ExportTemplateMetaViewIdstring(GUID)导出选择字段模板视图(MetaView)主键
IsFinalResultstring(bool)是否输出到最终结果"true" / "false"
IsDisabledstring(bool)是否禁用该节点"true" / "false"
orderstring同级排序例:"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)。

查询条件组装​

查询条件的组装优先级自高到低如下:

  1. context.FilterOverride(最高优先):一旦赋值,覆盖其他所有条件(主要用于触发器重新编辑条件场景),此时不再读取请求条件、默认条件与 AndFilter。
  2. request.Condition:请求体传入的条件,作为基础条件。
  3. 默认条件:由 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),切换模式不会互相覆盖;缺字段的行会被丢弃。
  4. 默认值占位符替换:对「基础条件 + 默认条件」合并后的 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 中的占位符不会被替换。
  5. context.AndFilter:链路按需插入的额外 AND 条件。

权限过滤​

  1. 查询操作权限:除非 SkipOperationPermission 生效,否则调用 HasPermissionAsync(Query) 校验 MetaObjectDataOperationType.Query。
    • SkipOperationPermission 取自节点 meta 或 context.DicParam,任一为 "true" 即跳过。
    • 无查询权限时:将 filter 置为 CommonConst.NotExistFilter(等价 _id = 74eb3e0a-416e-4faf-82bc-7e37effff4b1,一个不存在的主键),并跳过后续 MOU 过滤,记录告警日志(结果为空)。
  2. MOU(数据)权限:除非 SkipMouPermission 生效,且上一步未因无操作权限被短路,则通过 CombineDataPermissionFilterAsync(context, metaObject, filter, MouPermissionStageEnum.Query) 把 MOU 过滤条件以 AND 方式拼接。
    • SkipMouPermission 仅从 context.DicParam 读取。
    • MOU 过滤来源:优先 context.MouFilter(自定义脚本),否则按对象 Properties.MouEnabledForQuery / MouTypeForQuery 等配置生成(如「本人创建」「本人所在组织」「某人员字段等于当前用户」等)。

查询字段与排序​

查询字段(列)解析优先级:

  1. 节点 QueryFields(非空即用)。
  2. 否则若 request.Columns 有值(导出场景):取请求列,并把 code|name 拼接写入 context.DicParam["ChameleonExportColumns"]。
  3. 否则若 query 存在 metaViewId:取该视图 ListItems 的字段编码,并拼接 workflowdataid(用于渲染流程组件,所见即所得)。

随后:含 ~ 的 lookup 字段会补上其前缀基础字段;若最终有字段集合,则与对象字段编码取交集;最后始终追加 _id。

排序解析优先级:

  1. request.Sort(请求体传入,非空即用)。
  2. 否则节点 Sort(JSON 反序列化为 Dictionary<string, int>)。
  3. 否则默认 { "modifiedtime": -1 }。

之后移除不在对象字段集合中的排序键;大数据量分页时追加 _id 升序作为稳定分页的兜底排序。

执行与 SQL 形态​

  1. 判断是否跨对象(lookup)查询:递归检查 filter 中是否存在含 ~ 的字段。
  2. 计数:
    • 非跨对象:chameleonDbContext.GetCountAsync(metaObject.Code, filter)。
    • 跨对象:sqlManager.GetLookupQueryCountSql(...) 生成 SQL,用 chameleonDbContext.ExecuteScalarAsync(sql, param) 执行。
  3. 取列表:
    • 非跨对象:chameleonDbContext.GetListAsync(metaObject.Code, filter, columns, sort, skip, pageSize)。
    • 跨对象:sqlManager.GetLookupQueryListSql(...) 生成 SQL,用 chameleonDbContext.GetListBySqlAsync(sql, param) 执行。
  4. 大数据量分页分支:当 context.TinyTaskContext != null 且 QueryHugeData="true" 时,按 BatchOperationThreshold(100)为页大小逐页查询并累加,每页调用 TinyTaskContext.UpdateProgress(page, totalPages) 上报进度;否则单次按 request.Skip / request.PageSize 查询。

数据翻译​

每批结果都会执行两步翻译:

  1. dataSourceApp.TranslateAsync(result, metaObject._id, metaFields):把存储值转换为展示值(多语言、数据源等)。
  2. dataSourceApp.TranslateLookupAsync(result, metaFields, queryFields):按查询字段填充 lookup(关联)字段的展示内容。

输出与上下文​

输出项内容
context.CmpResultList<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) 作为接口最终返回值。

性能与限制​

  • 普通查询:请求 PageSize 若超过 CommonConst.DefaultQueryMax(10000)会被截断为 10000;无请求体时默认 Current=1、PageSize=30。
  • 大数据量查询:QueryHugeData="true" 时强制 Current=1、PageSize=ExportCountLimit(100000)。
  • 异步任务分页:按每页 BatchOperationThreshold(100)循环取数并上报进度。
  • 组件递归深度上限 100,超过抛出异常。

异常与校验​

校验阶段(_VerifyAsync):

场景异常
MetaObjectId 为空OperationObjectNotFound
对象不存在MetaObjectNotFoundById

执行阶段抛出的异常会通过 ErrorException 附带组件类型(type)、接口 ID、组件 ID,便于定位。