createStatusEngine

首发版本:3.00.6

语法

createStatusEngine(name, dummyTable, outputTable, keyColumn, [outputPattern="all"])

详情

创建一个按 keyColumn 维护最新记录的状态辅助引擎。引擎内部为每个 key 只保留最新一条记录(即“最新状态”)。无论 outputPattern 取何值,引擎内部始终维护一份最新状态表,每个 key 仅保留最后一条记录。可通过 select * from engineselect * from getStreamEngine(name) 查询当前所有 key 的最新状态。

引擎不解析输入中的任何状态标志,即使输入表包含名为 status 的列,也仅作为普通列处理。状态完全由引擎根据 key 是否已存在自动判定。

createStatusEngine 本身不做任何聚合计算,只负责为数据流标注 NEW/UPDATE 或按 key 去重。而 createTimeSeriesEngine / createReactiveStateEnginestatusColumn 参数是让流计算引擎读取并处理输入中的 NEW/UPDATE 标志,从而改变计算行为(例如遇到 UPDATE 时用新值替换窗口内最新值后重新聚合,而非累加)。

两者的典型协作方式:当上游数据源本身不携带状态标志时,先通过 createStatusEngine 自动补上 NEW/UPDATE,再将输出传入下游的时序聚合引擎/响应式状态引擎处理状态语义,以进行正确的聚合计算。

适用 createStatusEngine 的场景:

  • 下游不是时序聚合引擎/响应式状态引擎(如自定义 handler、keyedTable 或第三方消费者),需要通用的状态标注源。

  • 需要按 key 切换去重(即输入按同一 key 连续到来时只保留最后一条,key 变化时才输出)。

  • 多个下游引擎共享同一份状态标注,避免每个引擎重复判断。

  • 纯标注场景:只需知道“新增还是更新”,不需要做任何聚合。

输出模式

状态辅助引擎支持两种输出模式,通过参数 outputPattern 指定:

  • "all"(默认):每条输入均产生一条输出。引擎自动在输出末尾附加一个 SYMBOL 类型的状态列:

    • key 首次出现:输出 NEW。

    • key 已存在:输出 UPDATE。

    因此,outputTable 的 schema 必须为:全部输入列 + 末尾一个额外的 SYMBOL 列。

  • "keyChange":仅在 key 发生切换时输出上一个 key 段的最后一条记录,不输出状态列。同一 key 的连续输入只覆盖内部缓存,不触发输出。outputTable 的 schema 与输入表一致,无需额外列。

参数

name 字符串标量,表示状态引擎的名称,作为其在一个数据节点/计算节点上的唯一标识。可包含字母、数字和下划线,但必须以字母开头。

dummyTable 一个表对象,和输入的流数据表的 schema 一致,可以含有数据,亦可为空表。

outputTable 一个表对象,用于接收引擎的输出结果。创建引擎之前,需要将输出表预先设立为一个空表,并指定各列的列名以及数据类型。

输出表的列顺序如下:

  • 输入列。与 dummyTable 的全部列保持一致。

  • 状态列。若 outputPattern="all",则在末尾指定一个 SYMBOL 类型的列,由引擎自动写入 NEW 或 UPDATE。若 outputPattern="keyChange",则无需该列。

keyColumn 字符串标量或向量,表示分组列名。引擎根据该列维护每个 key 的最新状态,并判定输入记录是 NEW 还是 UPDATE。

outputPattern 可选参数,字符串标量,默认值为 "all"。指定引擎的输出模式,支持以下取值:

  • "all":每条输入均输出一条结果,附带引擎自动生成的状态列。

  • "keyChange":仅在 key 切换时输出上一个 key 段的最后一条记录,不输出状态列。

返回值

一个表对象,通过向该表对象写入,将数据注入状态辅助引擎。

例子

例 1. 本例演示 createStatusEngine 在默认 outputPattern="all" 模式下的行为。模拟一个股票行情流,引擎根据 sym 列判断每条记录是首次出现(NEW)还是已有更新(UPDATE),并在输出表末尾自动附加状态列。

try{ dropStreamEngine(`statusDemo) } catch(ex){}

// 定义输入表结构
dummy = table(10:0, `sym`time`price, [SYMBOL, TIMESTAMP, DOUBLE])
// 定义输出表:比输入表多一个 SYMBOL 类型的状态列
output = table(10:0, `sym`time`price`status, [SYMBOL, TIMESTAMP, DOUBLE, SYMBOL])

// 创建状态辅助引擎,按 sym 分组
engine = createStatusEngine(
    name="statusDemo",
    dummyTable=dummy,
    outputTable=output,
    keyColumn=`sym
)

// 构造模拟数据:A 出现 3 次,B 出现 1 次
input = table(`A`A`B`A as sym,
              2026.07.01T09:30:01.000 + 0 1000 2000 3000 as time,
              10.1 10.2 20.1 10.3 as price)
engine.append!(input)

select * from output
sym time price status
A 2026.07.01 09:30:01.000 10.1 NEW
A 2026.07.01 09:30:02.000 10.2 UPDATE
B 2026.07.01 09:30:03.000 20.1 NEW
A 2026.07.01 09:30:04.000 10.3 UPDATE
  • 第 1 条记录:A 首次出现,输出 NEW。

  • 第 2 条记录:A 已存在,输出 UPDATE。

  • 第 3 条记录:B 首次出现,输出 NEW。

  • 第 4 条记录:A 已存在(无论中间是否有其他 key 插入),输出 UPDATE。

此时查询引擎内部的最新状态,每个 key 只保留最后一条记录:

select * from engine
sym time price status
A 2026.07.01 09:30:04.000 10.3 UPDATE
B 2026.07.01 09:30:03.000 20.1 NEW

例 2. 输入存在业务 status 列。本例演示当输入表本身包含名为 status 的业务列时,createStatusEngine 不会解析该列,也不会将其作为 NEW/UPDATE 状态标志处理。该列会作为普通列原样输出;引擎生成的状态需要通过 outputTable 末尾额外添加的 SYMBOL 列(如 rowStatus)输出。

try{ dropStreamEngine(`statusBusinessDemo) } catch(ex){}

// 定义输入表结构:status 是普通业务列,不是引擎生成的状态列
dummy = table(10:0, `sym`time`status`price, [SYMBOL, TIMESTAMP, STRING, DOUBLE])
// 定义输出表:保留业务 status 列,并在末尾额外添加 rowStatus 用于存储引擎生成的 NEW/UPDATE
output = table(10:0, `sym`time`status`price`rowStatus, [SYMBOL, TIMESTAMP, STRING, DOUBLE, SYMBOL])

// 创建状态辅助引擎,按 sym 分组
engine = createStatusEngine(
    name="statusBusinessDemo",
    dummyTable=dummy,
    outputTable=output,
    keyColumn=`sym
)

// 构造模拟数据:status 列中的 raw1/raw2/raw3 是业务值,会被原样保留
input = table(`A`A`B as sym,
              2026.07.01T09:30:01.000 + 0 1000 2000 as time,
              "raw1" "raw2" "raw3" as status,
              10.1 10.2 20.1 as price)
engine.append!(input)

select * from output
sym time status price rowStatus
A 2026.07.01 09:30:01.000 raw1 10.1 NEW
A 2026.07.01 09:30:02.000 raw2 10.2 UPDATE
B 2026.07.01 09:30:03.000 raw3 20.1 NEW

可以看到,status 列中的 raw1、raw2、raw3 被原样保留;rowStatus 才是引擎根据 key 是否已存在自动生成的状态列。A 第一次出现时输出 NEW,第二次出现时输出 UPDATE;B 第一次出现时输出 NEW。

例 3. 本例演示 outputPattern="keyChange" 模式。该模式适用于输入数据按同一 key 连续成段到来的场景。引擎在 key 发生切换时,输出上一个 key 段的最后一条记录,实现有序去重。

try{ dropStreamEngine(`statusDedupDemo) } catch(ex){}

dummy = table(10:0, `sym`time`price, [SYMBOL, TIMESTAMP, DOUBLE])
// keyChange 模式不输出状态列,outputTable schema 与输入一致
output = table(10:0, `sym`time`price, [SYMBOL, TIMESTAMP, DOUBLE])

engine = createStatusEngine(
    name="statusDedupDemo",
    dummyTable=dummy,
    outputTable=output,
    keyColumn=`sym,
    outputPattern="keyChange"
)

// 模拟数据:A 连续 3 条,B 连续 2 条,C 1 条
input = table(`A`A`A`B`B`C as sym,
              2026.07.01T09:30:01.000 + 0 1000 2000 3000 4000 5000 as time,
              10.1 10.2 10.3 20.1 20.2 30.1 as price)
engine.append!(input)

select * from output
sym time price
A 2026.07.01 09:30:03.000 10.3
B 2026.07.01 09:30:05.000 20.2
  • A 段连续 3 条。当 key 从 A 切换到 B 时,输出 A 段的最后一条(price=10.3)。

  • B 段连续 2 条。当 key 从 B 切换到 C 时,输出 B 段的最后一条(price=20.2)。

  • C 段只有 1 条,由于之后没有新数据到来触发 key 切换,C 段暂未输出。

注:
keyChange 模式要求同一 key 的数据连续到来。如果数据交错(如 A, B, A, B),则每次 key 变化都会触发输出,无法达到按连续段去重的效果。

相关函数:createTimeSeriesEnginecreateReactiveStateEngine