跳转到内容

condition

这种数据来源直接从 DataStore 中获取动态数据(可以简单理解为从 DB 中获取数据)。通过配置 condition ,可以指定数据获取的 where 条件。

如:“condition”: “type == ‘Server’” 表示条件为模型字段为type,值为Server。

Condition 语法

目前支持特性:

  • 字符串:‘string’ 、“string”
  • 数字:1 、1.1
  • 变量:以英文字母开头的由英文、数字和下划线组成的连续字串
  • null :null
  • 括号:()
  • 数组:[]
  • 逻辑与和逻辑或:&& 、||
  • 单值比较运算:== 、!= 、> 、>= 、< 、<=
  • 数组比较运算:in 、!in
  • 字符串模糊匹配:contains
  • 动态推断比较运算:match
  • 下级字段:. ,例如 owner.name ,可连续多级
  • 内置变量:$currentUser 获取当前登陆用户 id

举例:

  • (a == 1 || b == 2) && (c == 3 || d == 4)
  • a > 1 && b >= 2 && c < 3 && d <= 4 && e == 5 && f != 6
  • a in [1, 2, 3] && b !in ['a', 'b', 'c'] && c in [var1, var2, 'string']
  • name contains 'Ive'
  • a match a && b match b
  • owner.name match name
  • a == null && b != null
  • user == $currentUser
  • company == $context.companyId

同时有几个限制:

  • 目前不支持取反操作,也就是类似 !(b < 2) 这样的逻辑是不支持的。
  • 目前也同样不支持比较运算的嵌套,也就是将一个比较运算作为另一个比较运算的右操作数,例如 a == (b > 2) 。
  • 比较运算左操作数只能是被查询模型的字段名,不允许是数字或字符串,也不能和右操作数左右互换。
  • match 的右操作数只能是变量,不可为常量。

match 比较

match 比较特别,是为了方便泛化使用条件表达式而专门强化的一个运算符,取决于传入的参数不同而不同。分别对应传入单值、集合值和范围值的情况,会分别被解析为被解析为 == value 、in values 、 >= value_start && <= value_end 。在大多数对变量的比较中,都可以直接使用 match ,Trantor 会自动进行处理。

关联模型比较

Trantor 的模型中的字段,可以是一个关联模型,对这种类型的字段进行比较时,默认使用 id 来比较。例如 owner == 1 实际上会被识别为类似 owner.id == 1 ,或者说按 GQL 的方式理解的话就是:

{
"owner": {
"id": 1
}
}

同样也支持 > 、< 和 in 、match 等其他的比较操作。

非 id 字段则需要显式指定:owner.name contains ‘username’ 。

查询值为空时忽略

目前条件表达式解析时,如果遇到右操作数对应的查询不存在时,整个条件分支会被丢弃,以便使一个查询条件表达式适用更多场景。举例 a > 1 && b == b 时,如果 queryValues 中 b 不存在,则实际为被执行的只有 a > 1 。

如果确实需要做空判断,需要在 queryValues 中传入一个确实的空值 {type: ‘One’, value: null}

自定义变量

当内置变量无法满足需求,查询需要带上业务相关的条件时,如当前公司 id ,可以使用此功能。

1:实现 ConditionHandler 中的 handler() 方法,并注册为 spring bean

public interface ConditionHandler {
interface HandlerConsumer {
void accept(TConditionContext context, ServletRequest request, ServletResponse response);
}
HandlerConsumer handler();
}
@Component
public class TestConditionHandler implements ConditionHandler {
@Override
public HandlerConsumer handler() {
return (context, request, response) -> context.addVariable("companyId", 1);
}
}

2:在 condition 中配置自定义变量

company == $context.companyId

注意

  • 如果该变量需要在别的模块复用,可以把添加变量的逻辑加入 api jar 中,在别的模块中引用即可。
  • 目前仅支持一级,即只能 . 一层

Condition 为空的默认推断行为

  • 当所属模型和入参模型相同

1:如果入参包含 id ,则 condition 默认为 id match id 。

2:如果入参不包含 id ,则 condition 默认为所有入参字段进行匹配,例如入参中包含 name 和 age ,则理解为 name match name && age match age 。

  • 当所属模型和目标模型不同

1:如果入参是单条数据条目,默认寻找第一个 relation 字段用作查询条件。

2:如果入参是多条数据条目,默认寻找第一个 relation 字段用作查询条件,按 IN 方式处理。

示例

示例一:

获取未冻结的学生信息 condition:“status != Frozen” 对应模型定义片段:

@TModel
class Student extends BaseModel<Long> {
// some other fields
@TModelField
private Status status;
}
enum Status {
Normal,
Frozen,
}

示例二:

使用入参商品的 id 查询对应的订单 condition:item == id 对应模型定义片段(等同于item.id == id,不写默认是等同模型中相同的参数):

@TModel
class Order extends BaseModel<Long> {
// some other fields
@TModelField @RelationMeta(name = "OrderItem")
private Item item;
}
@TModel
class Item extends BaseModel<Long> {
// item fields
}

示例三:

找出当前用户的,按固定时间段过滤的订单(时间段来自于 Form 提交) condition:buyer == $currentUser && createdAt match createdAt 对应模型定义片段:

@TModel
class Order extends BaseModel<Long> {
// some other fields
@TModelField @RelationMeta(name = "OrderBuyer")
private User buyer;
}`

注:

  • createdAt 字段定义在 BaseModel 中
  • createdAt match createdAt 的含义是目标模型中的 createdAt 字段匹配 Action 入参中的 createdAt 参数;其中 createdAt 参数由前一个视图的 Form 数据容器提供,在 Form 中 Date 类型字段会被渲染成一个时间段选择器,因此给出的结果其实是一个 Range<Date> ;match 会适配不同的参数结构,进行不同的匹配,对于 Range 则等同于 createdAt >= createdAt_start && createdAt <= createdAt_end