全部文档
文档中心DeepModel功能DeepQL常用语法与使用技巧三、带出关联数据:链接

三、带出关联数据:链接

除了对象的属性,还可以通过链接在结果中带出关联对象的数据:正向是「当前对象指向谁」,反向是「谁指向当前对象」。订单行通过链接 order 指向订单头;订单头还可通过链接 customerwarehouse 指向客户、仓库等主数据。

.链接编码 到达关联对象,在 select 的大括号里用嵌套形状写出要带出的属性。

  • 订单行 → 订单头:订单行有链接 order 指向订单头,在查订单行时可带出头的字段,例如 order: { order_no, order_date, status }

  • 订单头 → 主数据:订单头有链接 customerwarehouse 指向客户、仓库,可带出客户名(多语言字段,取中文名用 <str>.customer.name['zh-cn'])、仓库名等。

语法示例(查订单行,并带出所属订单头的订单号、日期):

Copy
select OrderLine {
    line_no,
    product_name,
    qty,
    price,
    order: { order_no, order_date, status }
}

多级时继续用 . 或嵌套;例如订单行的订单号也可写成 .order.order_no(见下文「多级与计算字段」)。

每条正向链接都有一条虚拟的反向链接:从「被指向的对象」看「谁指向我」。

  • 写法:.<链接名[is 对象类型],其中 < 表示反向,[is 对象类型] 指定链接另一端的对象类型。

  • 例如:订单行有正向链接 order 指向订单头,则在订单头上就有反向链接 .<order[is OrderLine],表示「指向当前订单头的所有订单行」。

典型用法是在头表上统计行表数量count(.<order[is OrderLine]) 表示该订单下的订单行数量。

  • 正向:.order.order_no.order.order_date 以及主数据 .customer.name(多语言 JSON)、.warehouse.name 可直接作为输出字段的表达式。客户名为多语言字段,取中文用 <str>.customer.name['zh-cn']

  • 在 select 里用 := 可给输出起别名,例如在订单头上把「客户中文名」「仓库名」「订单行数量」「订单行金额之和」作为单独字段:

Copy
select Order {
    order_no,
    order_date,
    status,
    customer_name := <str>.customer.name['zh-cn'],
    warehouse_name := .warehouse.name,
    line_count := count(.<order[is OrderLine]),
    total_amount := sum(.<order[is OrderLine].qty * .<order[is OrderLine].price)
}

查询最近 10 条已确认订单,并带出:订单号、日期、状态、客户名、仓库名、订单行数量、订单行金额合计。

Copy
select Order {
    order_no,
    order_date,
    status,
    customer_name := <str>.customer.name['zh-cn'],
    warehouse_name := .warehouse.name,
    line_count := count(.<order[is OrderLine]),
    total_amount := sum(.<order[is OrderLine].qty * .<order[is OrderLine].price)
}
filter .status = 'confirmed'
order by .order_date desc
limit 10

结果示意:

Copy
[
  {
    "order_no": "ORD003",
    "order_date": "2023-10-03",
    "status": "confirmed",
    "customer_name": "客户甲",
    "warehouse_name": "华北仓",
    "line_count": 2,
    "total_amount": 350.00
  },
  {
    "order_no": "ORD002",
    "order_date": "2023-10-02",
    "status": "confirmed",
    "customer_name": "客户乙",
    "warehouse_name": "华东仓",
    "line_count": 1,
    "total_amount": 99.00
  }
]

查链接数据时,有两种输出方式:拉平到第一层嵌套结构

:= 把链接对象的属性逐个「拉」到当前对象的第一层:

Copy
select OrderLine {
    line_no,
    product_name,
    qty,
    price,
    order_no := .order.order_no,
    order_date := .order.order_date,
    customer_name := <str>.order.customer.name['zh-cn']
}

结果是扁平的,每行所有字段都在同一层:

Copy
[
  { "line_no": 1, "product_name": "商品A", "qty": 2, "price": 50.00, "order_no": "ORD001", "order_date": "2023-10-01", "customer_name": "客户甲" },
  { "line_no": 2, "product_name": "商品B", "qty": 1, "price": 99.00, "order_no": "ORD001", "order_date": "2023-10-01", "customer_name": "客户甲" }
]

链接: { 属性 } 保持对象的嵌套关系:

Copy
select OrderLine {
    line_no,
    product_name,
    qty,
    price,
    order: {
        order_no,
        order_date,
        customer: { name }
    }
}

结果保留层级关系,链接对象作为子对象嵌在里面:

Copy
[
  {
    "line_no": 1, "product_name": "商品A", "qty": 2, "price": 50.00,
    "order": {
      "order_no": "ORD001", "order_date": "2023-10-01",
      "customer": { "name": { "zh-cn": "客户甲", "en": "Customer A" } }
    }
  }
]

反向链接同理——从头查行时,嵌套结构天然表达「一对多」:

Copy
select Order {
    order_no,
    lines := .<order[is OrderLine] {
        line_no,
        product_name,
        qty,
        price
    }
}

结果:一个订单头对象内嵌一个订单行数组,无需像 SQL 那样做 join 然后头信息重复 N 行:

Copy
[
  {
    "order_no": "ORD001",
    "lines": [
      { "line_no": 1, "product_name": "商品A", "qty": 2, "price": 50.00 },
      { "line_no": 2, "product_name": "商品B", "qty": 1, "price": 99.00 }
    ]
  }
]

拉平(:= 取值)

嵌套(链接: { } 展开)

输出结构

扁平,所有字段在同一层

层级,链接对象作为子对象

类似

传统 SQL join 后的表格

JSON / 文档型结构

适用

需要平铺表格、或只需取链接对象的个别字段

需要完整的关联对象结构、一对多场景

一对多时

每条关联对象独占一行,头信息重复

头只出现一次,子对象为数组

与传统 SQL 的区别:传统 SQL 只能输出二维表格(join 后头信息重复 N 行),而 DeepQL 天然支持嵌套结构,这是对象层查询语言的核心优势——结果直接就是结构化的数据,无需客户端再做拼装。

通过 Python SDK 等客户端拿到 DeepQL 的嵌套结果后,通常会得到一个含嵌套列的 DataFrame。如果需要将嵌套列展开为扁平行(类似 SQL join 的表格效果),可以使用 Pandas 的 行展开: df.explode()列展开: df.json_normalize() 方法:

Copy
import pandas as pd

# 假设 result 是 DeepQL 查询返回的嵌套结果(list of dict)
df = pd.DataFrame(result)

# lines 列是嵌套的数组,explode 展开为多行
df_flat = df.explode('lines')

# 再将 lines 中的字段拉平到列
lines_df = pd.json_normalize(df_flat['lines'])
df_flat = df_flat.drop(columns=['lines']).reset_index(drop=True)
df_flat = pd.concat([df_flat, lines_df], axis=1)

展开前:

order_no

lines

ORD001

[{“line_no”: 1, “product_name”: “商品A”, …}, {“line_no”: 2, …}]

展开后:

order_no

line_no

product_name

qty

price

ORD001

1

商品A

2

50.00

ORD001

2

商品B

1

99.00

在展开链接时,可以直接对链接的嵌套形状加 filterorder bylimit,只筛选/排序/截取需要的关联对象。

示例:查订单头,并只带出单价 > 50 的订单行(按单价降序,最多 5 行):

Copy
select Order {
    order_no,
    lines := .<order[is OrderLine] {
        line_no,
        product_name,
        price
    } filter .price > 50
      order by .price desc
      limit 5
}

注意:嵌套 filter 里的 .price 表示订单行的 price(作用域变为嵌套的对象类型),而非外层 Order 的属性。

当一条链接指向抽象类型联合类型时,链接的结果可能是多种子类型的混合。可用 [is 子类型] 进行类型交叉,只保留特定子类型的对象。

语法:链接[is 子类型][is 子类型].属性

此语法也可用于反向链接中,前文已见:.<order[is OrderLine] 就是一种类型交叉,指定反向链接另一端的对象类型。

概念

写法

说明

正向链接

.链接链接: { 属性 }

从当前对象到关联对象,带出对方属性(行→头)

反向链接

.<链接名[is 对象类型]

谁指向当前对象,常用于头表统计行数/金额

多级

.order.order_no

沿链接链逐级访问

计算字段

别名 := 表达式

在结果中输出聚合或表达式结果

嵌套 filter/order/limit

链接: { ... } filter ... order by ... limit N

对展开的链接做筛选、排序、截取

类型交叉

链接[is 子类型]

只保留特定子类型的链接对象

下一步可以让查询支持传入参数、用 with 复用中间结果,见「四、可复用与可传参:变量与 with」。

回到顶部

咨询热线

400-821-9199

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

ctrl+Enter to send