DeepModel 的所有模式信息(对象类型、属性、链接、约束等)都存储在内置的 schema 模块中,可以通过 自省查询(Introspection) 直接用 DeepQL 查询元数据——无需外部工具或额外接口。
自省查询的本质:schema 本身也是对象。DeepModel 把模式元数据建模为 schema::ObjectType、schema::Pointer(属性和链接的基类)等内置对象类型,你可以像查业务数据一样用 select / filter / order by 来查模式信息。
常用的自省类型:
|
自省类型 |
说明 |
|---|---|
|
|
对象类型(类似 SQL 的表) |
|
|
属性和链接的统一基类 |
|
|
属性(标量字段) |
|
|
链接(指向其他对象) |
|
|
标量类型(str、int64、json 等) |
|
|
注解(可存描述信息等自定义元数据) |
每个对象类型都有 .pointers 链接,指向该类型的所有属性和链接(Pointer)。每个 Pointer 有:
|
属性/链接 |
说明 |
|---|---|
|
|
字段编码 |
|
|
字段的目标类型(标量类型或对象类型) |
|
|
字段所属的对象类型 |
|
|
基数(One / Many) |
|
|
是否必填 |
|
|
是否只读 |
|
|
默认值表达式 |
|
|
计算字段的表达式(非计算字段为空) |
|
|
注解集合(如 |
|
|
目标类型是否内置——内置为属性(property),非内置为链接(link) |
select schema::ObjectType {
name
}
filter .name like 'default::%'
order by .name
default 是默认模块名。实际项目中模块名取决于部署配置(如 myapp::Order)。
select schema::ObjectType {
name,
pointers: {
name,
target_type := .target.name,
is_link := not .target.builtin,
cardinality := <str>.cardinality,
required,
readonly,
}
}
filter .name = 'default::Order'
结果示意:
[
{
"name": "default::Order",
"pointers": [
{ "name": "id", "target_type": "std::uuid", "is_link": false, "cardinality": "One", "required": true, "readonly": true },
{ "name": "order_no", "target_type": "std::str", "is_link": false, "cardinality": "One", "required": true, "readonly": false },
{ "name": "order_date", "target_type": "cal::local_date", "is_link": false, "cardinality": "One", "required": false, "readonly": false },
{ "name": "customer", "target_type": "default::Customer", "is_link": true, "cardinality": "One", "required": false, "readonly": false }
]
}
]
以下是一个实用的通用元数据查询,传入模块名,返回该模块下所有对象的属性和链接信息,包括字段编码、中文名(从注解中取)、类型、基数等:
with
current_module_prefix := <str>$current_module ++ "::",
builtin_pointer := {"id", "__type__", "order", "is_active"},
object_name := current_module_prefix ++ "%",
pointer := (
select schema::ObjectType
filter .name like object_name
).pointers,
pointer := (
select pointer {
anno_desc := assert_single((
select .annotations filter .name = 'std::description'
))
} {
field_id := <str>.id,
field_code := .name,
field_name := <str>json_get(to_json(.anno_desc@value), 'zh-cn'),
object_name := str_replace(.source.name, current_module_prefix, ''),
field_type := 'property' if .target.builtin else 'link',
data_type := str_replace(.target.name, current_module_prefix, ''),
}
filter
.name not in builtin_pointer
order by
.object_name
then .field_code
then .field_type desc
then .id
),
for p in pointer union (
select {
field_id := p.field_id,
field_code := p.field_code,
field_name := p.field_name,
object_name := p.object_name,
field_type := p.field_type,
data_type := p.data_type,
expr := p.expr,
cardinality := <str>p.cardinality,
required := p.required,
readonly := p.readonly,
default := p.default,
}
)
参数 $current_module 传入模块名(如 "default"),调用示例(Python SDK):
from deepfos.element.deepmodel import DeepModel
dm = DeepModel()
result = dm.query(deepql_string, current_module="default")
第一段 with:准备过滤条件
current_module_prefix := <str>$current_module ++ "::",
builtin_pointer := {"id", "__type__", "order", "is_active"},
object_name := current_module_prefix ++ "%",
拼接模块前缀(如 "default::"),用于后续 like 匹配。
builtin_pointer 定义需要排除的内置字段名集合。
第二段 with:取所有 Pointer 并提取注解
pointer := (
select schema::ObjectType
filter .name like object_name
).pointers,
先找到模块下所有对象类型,再通过 .pointers 取出所有属性和链接。
pointer := (
select pointer {
anno_desc := assert_single((
select .annotations filter .name = 'std::description'
))
} {
field_id := <str>.id,
field_code := .name,
field_name := <str>json_get(to_json(.anno_desc@value), 'zh-cn'),
object_name := str_replace(.source.name, current_module_prefix, ''),
field_type := 'property' if .target.builtin else 'link',
data_type := str_replace(.target.name, current_module_prefix, ''),
}
filter .name not in builtin_pointer
order by .object_name then .field_code then .field_type desc then .id
),
要点:
两层形状嵌套:第一层 { anno_desc := ... } 先把注解提取为计算字段,第二层 { field_id, field_code, ... } 基于第一层做进一步转换。这是一种「管道式」写法——先提取中间变量,再基于它计算最终字段。
assert_single(...) 确保每个字段最多只有一条 std::description 注解。
.anno_desc@value 用链接属性语法取注解的 value 值(注解值是 link property)。
json_get(to_json(...), 'zh-cn') 从多语言 JSON 中取中文名。
.target.builtin 为 true 说明目标是内置标量类型(str、int64 等),即属性(property);否则是自定义对象类型,即链接(link)。
for 循环:展开为扁平结果
for p in pointer union (
select {
field_id := p.field_id,
...
}
)
for ... union 遍历每个 Pointer,逐个构造自由对象并合并为最终结果集。这样输出是一张扁平的字段清单,方便导出或展示。
|
object_name |
field_code |
field_name |
field_type |
data_type |
cardinality |
required |
expr |
|---|---|---|---|---|---|---|---|
|
Customer |
code |
客户编码 |
property |
std::str |
One |
true | |
|
Customer |
name |
客户名称 |
property |
std::json |
One |
true | |
|
Order |
order_no |
订单编号 |
property |
std::str |
One |
true | |
|
Order |
order_date |
订单日期 |
property |
cal::local_date |
One |
false | |
|
Order |
status |
订单状态 |
property |
std::str |
One |
false | |
|
Order |
customer |
客户 |
link |
Customer |
One |
false | |
|
Order |
warehouse |
仓库 |
link |
Warehouse |
One |
false | |
|
OrderLine |
line_no |
行号 |
property |
std::int64 |
One |
true | |
|
OrderLine |
product_name |
商品名称 |
property |
std::str |
One |
true | |
|
OrderLine |
qty |
数量 |
property |
std::float64 |
One |
false | |
|
OrderLine |
price |
单价 |
property |
std::float64 |
One |
false | |
|
OrderLine |
order |
所属订单 |
link |
Order |
One |
true |
这张表就是模块的「数据字典」——一条查询拿到所有对象的完整字段结构,在项目交接、文档生成、动态表单构建等场景非常实用。
|
能力 |
说明 |
|---|---|
|
|
查询对象类型元数据 |
|
|
获取对象的所有属性和链接 |
|
|
区分属性(内置标量)和链接(自定义对象) |
|
|
从注解中取自定义元数据(如中文名) |
|
|
将集合展开为扁平的自由对象列表 |
|
自省 + 参数化 |
传入模块名,一条查询生成完整数据字典 |
下一步可了解窗口函数等进阶用法,见「十、进阶」。
回到顶部
咨询热线
