全部文档
文档中心DeepModel功能DeepQL常用语法与使用技巧九、自省查询(Introspection)

九、自省查询(Introspection)

DeepModel 的所有模式信息(对象类型、属性、链接、约束等)都存储在内置的 schema 模块中,可以通过 自省查询(Introspection) 直接用 DeepQL 查询元数据——无需外部工具或额外接口。

自省查询的本质:schema 本身也是对象。DeepModel 把模式元数据建模为 schema::ObjectTypeschema::Pointer(属性和链接的基类)等内置对象类型,你可以像查业务数据一样用 select / filter / order by 来查模式信息。

常用的自省类型:

自省类型

说明

schema::ObjectType

对象类型(类似 SQL 的表)

schema::Pointer

属性和链接的统一基类

schema::Property

属性(标量字段)

schema::Link

链接(指向其他对象)

schema::ScalarType

标量类型(str、int64、json 等)

schema::Annotation

注解(可存描述信息等自定义元数据)

每个对象类型都有 .pointers 链接,指向该类型的所有属性和链接(Pointer)。每个 Pointer 有:

属性/链接

说明

.name

字段编码

.target

字段的目标类型(标量类型或对象类型)

.source

字段所属的对象类型

.cardinality

基数(One / Many)

.required

是否必填

.readonly

是否只读

.default

默认值表达式

.expr

计算字段的表达式(非计算字段为空)

.annotations

注解集合(如 std::description

.target.builtin

目标类型是否内置——内置为属性(property),非内置为链接(link)

Copy
select schema::ObjectType {
    name
}
filter .name like 'default::%'
order by .name

default 是默认模块名。实际项目中模块名取决于部署配置(如 myapp::Order)。

Copy
select schema::ObjectType {
    name,
    pointers: {
        name,
        target_type := .target.name,
        is_link := not .target.builtin,
        cardinality := <str>.cardinality,
        required,
        readonly,
    }
}
filter .name = 'default::Order'

结果示意:

Copy
[
  {
    "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 }
    ]
  }
]

以下是一个实用的通用元数据查询,传入模块名,返回该模块下所有对象的属性和链接信息,包括字段编码、中文名(从注解中取)、类型、基数等:

Copy
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):

Copy
from deepfos.element.deepmodel import DeepModel

dm = DeepModel()
result = dm.query(deepql_string, current_module="default")

第一段 with:准备过滤条件

Copy
current_module_prefix := <str>$current_module ++ "::",
builtin_pointer := {"id", "__type__", "order", "is_active"},
object_name := current_module_prefix ++ "%",
  • 拼接模块前缀(如 "default::"),用于后续 like 匹配。

  • builtin_pointer 定义需要排除的内置字段名集合。

第二段 with:取所有 Pointer 并提取注解

Copy
pointer := (
    select schema::ObjectType
    filter .name like object_name
).pointers,
  • 先找到模块下所有对象类型,再通过 .pointers 取出所有属性和链接。

Copy
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 循环:展开为扁平结果

Copy
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

这张表就是模块的「数据字典」——一条查询拿到所有对象的完整字段结构,在项目交接、文档生成、动态表单构建等场景非常实用。

能力

说明

schema::ObjectType

查询对象类型元数据

.pointers

获取对象的所有属性和链接

.target.builtin

区分属性(内置标量)和链接(自定义对象)

.annotations + @value

从注解中取自定义元数据(如中文名)

for ... union

将集合展开为扁平的自由对象列表

自省 + 参数化

传入模块名,一条查询生成完整数据字典

下一步可了解窗口函数等进阶用法,见「十、进阶」。

回到顶部

咨询热线

400-821-9199

我们使用 ChatGPT,基于文档中心的内容以及对话上下文回答您的问题。

ctrl+Enter to send