查询前动态拼接过滤条件
本文档介绍如何在「查询集合组件」之前放置 C# 脚本 组件,通过 context.AndFilter 动态拼接查询过滤条件。
使用场景
当查询条件无法在「查询集合组件」中预先配置、需要在链路运行时才确定时,例如:
- 条件取值来自上游组件的计算结果(如:先查配置表,再按其结果过滤目标数据)
- 需要根据前端传入参数动态决定过滤范围
- 需要把多个来源的条件组合成复杂的 And / Or 逻辑
- 需要保留「查询集合组件」的请求条件与默认条件,只在其基础上「追加」条件
实现方式
流程配置
context.AndFilter 是在「查询集合组件」执行时才被读取的,因此 C# 脚本组件必须放在查询集合组件之前。
流程说明:
- 开始节点 - 流程入口
- C# 脚本组件 - 计算并设置
context.AndFilter - 查询集合组件 - 组装条件时把
context.AndFilter以 And 关系拼入,再执行查询 - 结束组件 - 流程结束,返回查询结果
示例代码
以下示例演示在查询前追加「启用状态且在今日之后创建」的条件:
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Chameleon.Common;
using Chameleon.Common.Context;
using Chameleon.Common.Exceptions;
using Chameleon.Common.Models;
using Chameleon.Database;
using Chameleon.SDK;
public class ChameleonCSharpScript
{
public string Execute(ComponentContext context, ChameleonSDK sdk)
{
// 只查询启用状态、且创建时间在今天之后的数据
context.AndFilter = FilterBuilder.And(
FilterBuilder.Eq("status", "active"),
FilterBuilder.Gte("createdTime", DateTime.Today)
);
return null;
}
}
关键点说明
1. context.AndFilter 属性
- 类型为
DynamicFilter,用于在条件链路上「按需插入」额外的查询条件。 - 多个条件用
FilterBuilder.And(...)/FilterBuilder.Or(...)组合,条件与操作符写法见 查询操作符说明。 - 未被赋值(
null)时不产生任何额外条件。
2. 条件拼接顺序
「查询集合组件」(DbQueryListComponentManager)组装最终条件时,按以下顺序执行:
- 若设置了
context.FilterOverride,直接用它覆盖全部条件,后续条件全部失效(AndFilter不再生效)。 - 否则以请求条件
request.Condition为基础,And 上「默认条件」(基础模式 / 高级模式的默认条件)。 - 对合并后的条件执行默认值占位符替换(
{Env.*}/{Model.*})。 - 最后把
context.AndFilter以 And 关系拼入。 - 再依次拼入查询操作权限与 MOU 数据权限过滤。
因此 context.AndFilter 是「追加」到既有条件之上的,不会覆盖请求条件与默认条件。
3. 与 FilterOverride 的区别
| 属性 | 与既有条件的关系 | 说明 |
|---|---|---|
AndFilter | 追加(And) | 保留请求条件与默认条件,再叠加自身 |
FilterOverride | 覆盖 | 直接替换全部条件(MOU 除外),AndFilter 随之失效 |
需要「在默认条件基础上追加」时用 AndFilter;需要「完全自定义查询条件」时用 FilterOverride。
4. 占位符不会在 AndFilter 中生效
默认值占位符(如 {Env.LoginUserId}、{Model._id})只对「请求条件 + 默认条件」执行替换,而 context.AndFilter 是在其后才拼入的,因此占位符写在 AndFilter 中不会被替换,需要在脚本中直接使用真实值。
扩展示例
示例1:根据前端请求参数拼接条件
前端可在请求的 extend 中携带自定义参数,脚本读取后用其构成条件:
public string Execute(ComponentContext context, ChameleonSDK sdk)
{
// 读取前端请求 extend 中的自定义参数
string categoryId = null;
context.Request.Extend?.TryGetValue("categoryId", out categoryId);
if (!string.IsNullOrEmpty(categoryId))
{
context.AndFilter = FilterBuilder.Eq("categoryId", categoryId);
}
return null;
}
示例2:根据上游组件传递的值拼接条件
上游组件可通过 DicParam 传递字符串值,本组件读取后再拼接条件:
public string Execute(ComponentContext context, ChameleonSDK sdk)
{
if (context.DicParam.TryGetValue("TargetOrgId", out var orgId)
&& !string.IsNullOrEmpty(orgId))
{
context.AndFilter = FilterBuilder.Eq("organization", orgId);
}
return null;
}
示例3:复杂的 And / Or 组合
public string Execute(ComponentContext context, ChameleonSDK sdk)
{
context.AndFilter = FilterBuilder.And(
FilterBuilder.Eq("status", "active"),
FilterBuilder.Or(
FilterBuilder.Eq("level", "high"),
FilterBuilder.Gte("amount", 10000)
)
);
return null;
}
示例4 :追加到已有的 AndFilter
如果链路中已有组件设置过 AndFilter,应在其基础上追加,而不是直接赋值覆盖:
public string Execute(ComponentContext context, ChameleonSDK sdk)
{
var extra = FilterBuilder.Eq("isDeleted", false);
context.AndFilter = context.AndFilter != null
? FilterBuilder.And(context.AndFilter, extra)
: extra;
return null;
}
注意事项
- 节点顺序:C# 脚本组件必须位于查询集合组件之前,否则查询已执行完毕,
AndFilter不再生效。 - 不要与 FilterOverride 同时使用:一旦设置了
FilterOverride,AndFilter会被忽略。 - 占位符:
{Env.*}/{Model.*}占位符在AndFilter中不生效,请直接使用真实值。 - 适用组件:
context.AndFilter会被查询集合、查询数量、分组聚合查询以及实体数据源查询读取并拼接,其余查询类组件请以各自文档为准。 - 数据权限不受影响:
AndFilter只追加业务条件,MOU 数据权限过滤仍会独立拼接。
常见 问题
Q: 为什么设置了 AndFilter 但查询结果没有变化?
A: 常见原因有两个:一是 C# 脚本组件放在了查询集合组件之后;二是查询集合组件设置了 FilterOverride,覆盖了包括 AndFilter 在内的全部条件。
Q: AndFilter 会覆盖默认条件吗?
A: 不会。AndFilter 与请求条件、默认条件是 And 关系,只会进一步缩小结果集。
Q: 如何完全接管查询条件?
A: 使用 context.FilterOverride 直接指定条件(MOU 数据权限过滤除外)。