ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

StarRocks json_length 函数详解:JSON 文档与路径长度的计算规则、实操与源码实现

StarRocks json_length 函数详解:JSON 文档与路径长度的计算规则、实操与源码实现 StarRocks json_length 函数详解JSON 文档与路径长度的计算规则、实操与源码实现【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocksjson_length是 StarRocks 中用于衡量 JSON 文档“规模”的核心查询函数它返回 JSON 文档的顶层长度也可通过 JSON Path 参数定位文档内部某个值并返回其长度。本篇基于官方文档docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_length.md的完整语义规则结合 StarRocks BE 引擎源码实现与单元测试讲清该函数的计算规则、边界行为和底层执行路径读完后可在分析型查询中正确运用json_length做数据质量校验、结构探测并理解其在 flat JSON 与 full JSON 两种存储形态下的执行差异。一、功能概述与长度计算规则json_length返回一个 JSON 文档的长度length。如果指定了 path 参数则返回该路径所标识的值的长度。StarRocks 全部 JSON 函数与运算符可在 JSON 函数概览页 中统一查阅此外还可结合 generated columns 将 JSON 提取结果固化为列加速高频查询。文档中明确了“长度”的四条计算规则这也是使用该函数前必须建立的心智模型值的形态长度计算方式文档示例标量值scalar长度恒为 11、a、true、false、null的长度均为 1数组array等于数组元素个数[1, 2]的长度为 2对象object等于对象成员个数{a: 1}的长度为 1嵌套结构不计入长度{a: [1, 2]}的长度为 1嵌套数组[1, 2]不计最后一条规则是实践中最容易踩坑的点json_length只统计顶层的数组元素数或对象成员数不会递归展开嵌套的数组或对象。例如{a: [1, 2], b: [3]}的长度是 2 而不是 4。如果确实需要统计深层结构应先用 JSON 路径表达式 定位到目标层级如json_length(doc, $.a)再计算该子值的长度。二、语法与参数语法json_length(json_doc[, path])参数json_doc必填要返回长度的 JSON 文档。既可以是 JSON 类型的列也可以是字符串字面量。path可选用于返回文档内部某个值的长度。路径通常以$开头以.作为路径分隔符数组下标使用[]且从 0 开始计数。从 BE 源码可以印证path在引擎内部由JsonPath解析器处理支持点号访问对象成员、下标访问数组元素等标准 JSON Path 写法。三、返回值语义与边界行为json_length返回INT 类型文档对三类特殊场景给出了明确约定JSON 文档不是合法文档时返回错误。以下任一场景返回 0path没有标识出文档中的任何值路径在文档中不存在path 不是一个合法的路径表达式path 中包含*或**通配符。关于第 2 点结合 BE 源码json_functions.cpp可以看到更细粒度的实现事实在 full JSON 路径中当 path 表达式无法被解析时get_prepared_or_parse会返回失败此时该实现分支对该行 append 的是 NULL 而非 0当 path 合法但未命中任何值提取结果为isNone()时才返回 0。也就是说从源码结构看返回 0 主要覆盖路径合法但未命中以及 flat JSON 场景下的部分匹配partial match情形而解析失败的具体输出取决于 JSON 存储形态。在 SQL 层编写断言逻辑时建议用IS NULL与 0双重判断覆盖这两类异常路径。四、官方示例全集以下示例完整继承自文档可直接复制执行。示例 1返回标量值的长度。select json_length(1); ------------------ | json_length(1) | ------------------ | 1 | ------------------示例 2返回空对象的长度。select json_length({}); ------------------- | json_length({}) | ------------------- | 0 | -------------------示例 3返回含数据对象的长度。select json_length({Name: Homer}); ---------------------------------- | json_length({Name: Homer}) | ---------------------------------- | 1 | ----------------------------------示例 4返回 JSON 数组的长度。select json_length([1, 2, 3]); -------------------------- | json_length([1, 2, 3]) | -------------------------- | 3 | --------------------------示例 5返回含嵌套数组的 JSON 数组的长度。嵌套数组[3, 4]作为一个元素计数其内部元素不计入长度。select json_length([1, 2, [3, 4]]); ------------------------------- | json_length([1, 2, [3, 4]]) | ------------------------------- | 3 | -------------------------------示例 6返回 path$.Person指定对象的长度。先通过SET将 JSON 文档放入会话变量再按路径取值SET file { Person: { Name: Homer, Age: 39, Hobbies: [Eating, Sleeping] } }; select json_length(file, $.Person) Result;示例 7返回 path$.y指定值的长度。此处$.y是数组[1, 2]故长度为 2select json_length({x: 1, y: [1, 2]}, $.y); --------------------------------------------- | json_length({x: 1, y: [1, 2]}, $.y) | --------------------------------------------- | 2 | ---------------------------------------------五、BE 源码实现解析5.1 入口分发flat JSON 与 full JSON 双路径json_length在 FE 侧注册为常量函数名FunctionSet.java 中public static final String JSON_LENGTH json_lengthBE 侧由JsonFunctions::json_length承担执行json_functions.cpp。入口实现非常简短StatusOrColumnPtr JsonFunctions::json_length(FunctionContext* context, const Columns columns) { RETURN_IF_COLUMNS_ONLY_NULL(columns); const auto* cc ColumnHelper::get_data_column(columns[0].get()); const JsonColumn* js down_castconst JsonColumn*(cc); if (js-is_flat_json()) { return _flat_json_length(context, columns); } return _full_json_length(context, columns); }从源码结构看引擎依据JsonColumn是否带有扁平化子列is_flat_json()将执行分派到两条路径_flat_json_length适用于已经做过 JSON 扁平化常见于带 JSON 下标列的表如预提取了$[a]路径列的场景此时 path 表达式在 fragment 初始化阶段就已解析并固化为state-real_path执行期只需对每行做快速提取_full_json_length适用于完整 JSON 文档若传入 path 参数则逐行解析/复用已 prepared 的JsonPath后调用JsonPath::extract提取子值。5.2 核心长度计算VelocyPack Slice 的 length()两条路径的长度判定逻辑完全同构核心代码为if (target_slice.isObject() || target_slice.isArray()) { result.append(target_slice.length()); // 对象/数组成员数或元素数 } else if (target_slice.isNone()) { result.append(0); // 未命中任何值 } else { result.append(1); // 标量 }见 json_functions.cpp这直接印证了文档的四条规则StarRocks 的 JSON 值内部以 VelocyPackvpack二进制格式存储vpack::Slice::length()对对象返回成员数、对数组返回元素数标量统一计 1。target_slice.isNone()分支对应文档中路径未标识出值时返回 0的语义。值得注意的是 full JSON 路径中若 path 字符串解析失败该行结果为 NULLauto jsonpath get_prepared_or_parse(context, path_str, stored_path); if (UNLIKELY(!jsonpath.ok())) { result.append_null(); continue; }而_flat_json_length中还存在state-is_partial_match分支——当扁平化路径只部分覆盖提取目标时同样先extract再按 object/array/scalar 三态判定长度保证两种存储形态下语义一致。5.3 单元测试佐证BE 为json_length提供了两组参数化测试json_functions_test.cpp覆盖文档中的全部核心规则INSTANTIATE_TEST_SUITE_P(JsonLengthTest, JsonLengthTestFixture, ::testing::Values( std::make_tuple(R({ k1:1, k2: 2 }), , 2), // 对象成员数 std::make_tuple(R({ k1:1, k2: {} }), $.k2, 0), // 空对象 std::make_tuple(R({ k1:1, k2: [1,2] }), $.k2, 2), std::make_tuple(R({ k1:1, k2: [1,2] }), $.k3, 0), // 路径未命中 std::make_tuple(R( { }), , 0), std::make_tuple(R( [] ), , 0), std::make_tuple(R( [1] ), , 1), std::make_tuple(R( null ), , 1), // 标量含 null长度为 1 std::make_tuple(R( 1 ), , 1) ));FlatJsonLengthTestFixture同文件 L1413 起则以JsonFlattener构造扁平化列重复验证上述用例在 flat JSON 形态下的等价结果。这组测试与文档规则一一对应可作为行为正确性的权威依据。六、实战建议数据质量校验在导入后校验 JSON 字段是否符合预期结构时json_length(col) 0可快速筛出空对象/空数组行json_length(col) 预期成员数可筛出字段缺失行。嵌套结构的分层统计由于嵌套不计入长度统计深层数组规模时应链式使用 path 参数例如json_length(events, $.details.tags)而不是对整文档取长度。加速高频 JSON 探测对于反复使用json_length(doc, $.field)或同类提取的场景可参照 generated columns 文档 将提取结果物化为生成列避免每行重复解析。通配符不适用path 含*/**时函数按约定返回 0 而非集合长度需要集合语义时应改用其他 JSON 函数组合或先展开再计数。参考路径文档json_length 官方文档、JSON 函数概览实现BE json_length 实现、函数声明、FE 函数名注册测试json_length 单元测试、flat JSON 测试进阶generated columns【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表