全部文档
文档中心DeepModel功能DeepQL常用语法与使用技巧四、可复用与可传参:变量与 with

四、可复用与可传参:变量与 with

同一句查询需要根据「外部传入的值」或「中间算出的集合」来过滤、复用时,可以用查询变量(传参)和 with 区块。

$变量名 表示从外部传入的值,并在前面用类型声明,例如 <str>$order_no

写法

说明

<str>$order_no

必填,字符串

<optional str>$status

非必填,字符串;不传时为空

DeepModel 属性类型与 DeepQL 变量类型对应关系:

DeepModel 属性类型

DeepQL 变量类型

文本

<str>$var

多语言文本

<json>$var

布尔值

<bool>$var

整数

<int64>$var

小数

<decimal>$var

日期时间

<cal::local_datetime>$var

枚举值

<str>$var

文件

<json>$var

UUID

<uuid>$var

比较时可使用 ?=?!= 以便与空值比较(可选参数未传时)。

在 select 前用 with 定义变量,多个变量用逗号分隔,用 := 赋值。

Copy
with 变量名 := 表达式,
     另一变量 := 另一表达式
select ...

变量可以是:传参(如 order_no := <str>$order_no)、子查询结果、或标量表达式。主查询的 filter、select 中可直接使用这些变量。

查询指定订单号对应的订单头信息(订单号、日期、状态、客户名、仓库名、订单行数、订单行金额合计)。

Copy
with order_no := <str>$order_no

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 .order_no = order_no

传参示例:order_no 传入 "ORD001"

结果示意:

Copy
[
  {
    "order_no": "ORD001",
    "order_date": "2023-10-01",
    "status": "draft",
    "customer_name": "客户甲",
    "warehouse_name": "华北仓",
    "line_count": 2,
    "total_amount": 199.00
  }
]

查询指定客户的订单;若不传客户编码则查全部订单。使用 <optional str>$customer_code?=

Copy
with customer_code := <optional str>$customer_code

select Order {
    order_no,
    order_date,
    status,
    customer_name := <str>.customer.name['zh-cn']
}
filter .customer.code ?= customer_code

传参 customer_code

含义

"C001"

只查客户编码为 C001 的订单

不传或 null

查全部订单

先算出「指定状态的订单」及其行数、行金额,再基于此算每单平均行金额等。

查询指定状态的订单及其:订单号、日期、订单行数、订单行金额合计、平均行金额(总金额/行数,行数为 0 时为 0)。

Copy
with status_filter := <str>$status,
     OrderInfo := (
         select Order {
             order_no,
             order_date,
             line_count := count(.<order[is OrderLine]),
             total_amount := sum(.<order[is OrderLine].qty * .<order[is OrderLine].price)
         }
         filter .status = status_filter
     )

select OrderInfo {
    order_no,
    order_date,
    line_count,
    total_amount,
    avg_line_amount := .total_amount / .line_count if .line_count != 0 else 0
}

结果示意:

Copy
[
  {
    "order_no": "ORD002",
    "order_date": "2023-10-02",
    "line_count": 1,
    "total_amount": 99.00,
    "avg_line_amount": 99.00
  }
]

实际业务中经常需要传入一组值(如多个订单号),用 in 做批量过滤。DeepQL 不直接支持数组类型参数,但可以通过 JSON 数组 + json_array_unpack 实现列表传参。

  1. 客户端将列表序列化为 JSON 数组字符串,如 '["ORD001", "ORD003", "ORD005"]'

  2. DeepQL 中用 <json>$变量名 接收,再用 json_array_unpack() 解包为集合。

  3. 如果列表元素需要转为特定类型(如 str),在外层再加一层类型转换:<str>json_array_unpack(<json>$变量名)

按传入的订单号列表,查询这些订单及其订单行(嵌套结构),按订单号排序:

Copy
with order_no_list := <str>json_array_unpack(<json>$order_no_list)

select Order {
    order_no,
    order_date,
    status,
    customer_name := <str>.customer.name['zh-cn'],
    lines := .<order[is OrderLine] {
        line_no,
        product_name,
        qty,
        price
    } order by .line_no
}
filter .order_no in order_no_list
order by .order_no
Copy
import json
from deepfos.element.deepmodel import DeepModel

dm = DeepModel()

# 要查询的订单号列表
order_nos = ["ORD001", "ORD003", "ORD005"]

ql = """
    with order_no_list := <str>json_array_unpack(<json>$order_no_list)

    select Order {
        order_no,
        order_date,
        status,
        customer_name := <str>.customer.name['zh-cn'],
        lines := .<order[is OrderLine] {
            line_no,
            product_name,
            qty,
            price
        } order by .line_no
    }
    filter .order_no in order_no_list
    order by .order_no
"""

# 列表参数需要 json.dumps 序列化为 JSON 数组字符串
result = dm.query_object(ql, order_no_list=json.dumps(order_nos))

传参说明:

Python 端

传到 DeepQL 的值

DeepQL 中解包后

["ORD001", "ORD003"]

'["ORD001","ORD003"]'(JSON 字符串)

{'ORD001', 'ORD003'}(str 集合)

Copy
[
  {
    "order_no": "ORD001",
    "order_date": "2023-10-01",
    "status": "draft",
    "customer_name": "客户甲",
    "lines": [
      { "line_no": 1, "product_name": "商品A", "qty": 2, "price": 50.00 },
      { "line_no": 2, "product_name": "商品B", "qty": 1, "price": 99.00 }
    ]
  },
  {
    "order_no": "ORD003",
    "order_date": "2023-10-03",
    "status": "confirmed",
    "customer_name": "客户丙",
    "lines": [
      { "line_no": 1, "product_name": "商品C", "qty": 5, "price": 30.00 }
    ]
  }
]

同样的方式也适用于日期区间等列表场景。例如传入日期区间 ["2023-10-01 00:00:00", "2023-10-31 23:59:59"],在 DeepQL 中取下标:

Copy
with date_range := <json>$date_range,
     min_date := <cal::local_datetime>date_range[0],
     max_date := <cal::local_datetime>date_range[1]

select Order {
    order_no,
    order_date,
    status
}
filter .order_date >= min_date and .order_date <= max_date

Python 端:

Copy
result = dm.query_object(ql, date_range=json.dumps(["2023-10-01 00:00:00", "2023-10-31 23:59:59"]))

能力

写法

说明

传参

<str>$var<optional str>$var

在 filter/select 中使用变量

列表传参

<str>json_array_unpack(<json>$var)

传入 JSON 数组,解包为集合,配合 in 使用

日期区间传参

<cal::local_datetime>(<json>$var)[0]

JSON 数组取下标后转类型

with

with 变量 := 表达式

定义可在主查询中复用的变量或子查询

空值比较

?=?!=

与可选参数或空集比较时使用

下一步可以学习用子查询得到集合、用 in / detached 等,见「五、子查询与集合关系」。

回到顶部

咨询热线

400-821-9199

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

ctrl+Enter to send