尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

StarRocks json_contains 函数完全指南:JSON 包含关系判定与源码级实现解析

StarRocks json_contains 函数完全指南:JSON 包含关系判定与源码级实现解析 StarRocks json_contains 函数完全指南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_contains是 StarRocks 提供的 JSON 查询与处理函数之一用于判断一个目标 JSON 文档是否包含特定的候选值或子文档。它在日志解析、配置校验、标签检索、半结构化数据过滤等场景中非常实用无需展开整个 JSON一条 SQL 即可在 BE 端完成深层的包含关系判定。读完本文你将掌握json_contains的完整语法、参数约定、各类 JSON 类型的包含语义与边界行为并能结合 json_functions.cpp 的源码理解其底层递归实现与测试覆盖。函数概述json_contains执行的是目标文档包含候选文档的判定如果目标 JSON 文档包含候选 JSON 值函数返回1否则返回0。json_contains(json_target, json_candidate)该函数与json_exists、json_query等函数同属于 JSON 查询与处理函数族完整函数清单见 overview-of-json-functions-and-operators.md。参数说明参数类型说明json_targetJSON目标 JSON 文档的表达式。可以是一个 JSON 类型的列也可以是由PARSE_JSON等 JSON 构造函数产出的 JSON 对象json_candidateJSON需要在目标中搜索的候选 JSON 值或子文档的表达式。同样可以是 JSON 列或PARSE_JSON等构造函数的结果两个参数都是 JSON 类型的表达式因此实际使用中既可以直接传 JSON 列也可以通过PARSE_JSON(...)动态构造 JSON 字面量参与判定。返回值返回 BOOLEAN 值1目标 JSON 文档包含候选值或子文档0目标 JSON 文档不包含候选值或子文档。需要特别说明从 BE 端实现看json_functions.cpp当json_target或json_candidate中任意一个为 SQL NULL 时json_contains返回 NULL 而非0。这一点在使用可为空的 JSON 列时需格外留意建议配合COALESCE或WHERE ... IS NOT NULL处理。包含语义Usage notesjson_contains的包含判定遵循类型驱动的递归规则不同类型的候选值对应不同的判定逻辑标量值字符串、数字、布尔值、null目标与候选值相等时返回true否则返回falseJSON 对象目标对象包含候选对象的所有键值对时返回true目标可以有额外键候选的每个键值对必须在目标中按值精确匹配JSON 数组候选是数组时目标数组包含候选数组的所有元素即返回true候选是单个值标量时只要该值出现在目标数组的某个元素中即返回true候选是对象时目标数组中所有候选对象的键值对都能在数组元素中找到即返回true嵌套结构对嵌套结构执行深度包含检查但对象键值对的比对仍要求目标中对应键的值与候选值精确相等而不是对目标中更深层嵌套的子树做搜索式包含。最后一个要点最容易踩坑json_contains判定的是同层级的包含并不会在目标 JSON 中递归搜索候选子文档。例如目标为{x: {a: 1}}、候选为{a: 1}时虽然候选是目标中嵌套对象的内容但由于目标对象自身没有键a判定结果为false。这一点在 json_functions_test.cpp 的测试用例中有明确覆盖。使用示例示例 1对象包含特定键值对mysql SELECT json_contains(PARSE_JSON({a: 1, b: 2}), PARSE_JSON({a: 1})); - 1目标对象比候选对象多出键b不影响判定结果——只要候选的全部键值对被目标包含即可。示例 2对象不包含指定键值对mysql SELECT json_contains(PARSE_JSON({a: 1, b: 2}), PARSE_JSON({c: 3})); - 0候选键c在目标中不存在返回0。同样即使键存在但值不相等如候选{a: 2}、目标{a: 1}也会返回0。示例 3数组包含多个元素mysql SELECT json_contains(PARSE_JSON([1, 2, 3, 4]), PARSE_JSON([2, 3])); - 1目标数组包含候选数组的全部元素2和3且不要求顺序一致返回1。示例 4数组包含单个标量值mysql SELECT json_contains(PARSE_JSON([1, 2, 3, 4]), PARSE_JSON(2)); - 1候选是单个标量2只要它作为目标数组的某个元素存在即返回1。示例 5数组不包含指定元素mysql SELECT json_contains(PARSE_JSON([1, 2, 3, 4]), PARSE_JSON([5, 6])); - 0候选元素5、6均不在目标数组中返回0。示例 6嵌套结构中的包含判定mysql SELECT json_contains(PARSE_JSON({users: [{id: 1, name: John}, {id: 2, name: Jane}]}), PARSE_JSON({users: [{id: 1}]})); - 0这个例子是新手最容易误判的场景。虽然目标数组中有{id: 1, name: John}这样的对象但数组包含要求元素级的精确匹配候选数组元素是{id: 1}而目标数组中的元素是{id: 1, name: John}两者并不精确相等因此结果为0。换言之数组内对象只做整元素相等比对不做对象内部的部分匹配。源码级实现解析理解json_contains的精确行为最可靠的方式是阅读 BE 端实现。json_functions.cpp 中JsonFunctions::json_contains以向量化方式处理整列数据通过ColumnViewerTYPE_JSON分别读取目标列与候选列逐行跳过 NULL 值并追加 NULL 结果对非空行调用json_value_contains(target_json, candidate_json)得到布尔结果最后用ColumnBuilderTYPE_BOOLEAN构建结果列并利用ColumnHelper::is_all_const做常量折叠优化。真正的包含判定核心是 JsonContainmentChecker 这个递归检查器其逻辑与文档语义一一对应空值前置处理候选为 JSON null 时直接返回true目标为 null 且候选非 null 时返回false直接相等短路先调用JsonValue::compare判断目标与候选整体是否相等相等则直接返回true对象包含对象check_object_contains_object遍历候选对象的每个键值对要求目标hasKey(key)且JsonValue::compare(target.get(key), item.value) 0任一不满足即返回false数组的三种分支候选为数组check_array_contains_array对候选的每个元素在目标数组中寻找一个满足contains(target_item, cand_item)的元素候选为对象check_array_contains_distributed_object允许候选对象的键值对分散在目标数组的不同元素中只要每个键值对都能在某个数组对象元素里精确匹配即可候选为标量check_array_contains_value只要目标数组的任意元素contains(target_item, candidate)即返回true其余类型组合例如目标是标量、候选是对象/数组等不匹配的组合返回false。从源码结构可以推断数组内的包含判定是递归的候选数组元素与目标数组元素之间仍会走contains的全套规则因此[{a: 1}, {b: 2}]包含[{a: 1}]这类数组内对象整体相等的场景可以成立但{a: [1, 2]}是否包含{a: [1]}则取决于[1, 2]与[1]这两个数组元素间的递归比较——后者的元素1与目标数组元素1、2逐个比对时1可以匹配到1此时应当返回true。需要注意的是对象键值比对走的是compare 0的精确相等分支对应 json_functions.cpp而非递归contains因此{a: 1}不会因目标中a的值是更复杂的嵌套结构而部分包含成立。测试验证行为边界的完整覆盖BE 端对json_contains有专门的参数化单测JsonContainsTestFixture位于 json_functions_test.cpp。测试以(目标JSON, 候选JSON, 期望结果)三元组驱动覆盖了以下行为边界标量相等性hello包含hello为真hello包含world为假数字、布尔、null 同理对象子集语义{a: 1, b: 2}包含{a: 1}、{b: 2}、自身均为真包含{c: 3}、{a: 2}键在但值不同为假多键对象的任意子集三键对象包含任意两键子集均为真只要多出一个不存在的键或任一值不匹配即为假数组元素包含[1, 2, 3]包含[1, 2]、[2, 3]与自身不包含[4, 5]类型敏感[1, 2, 3]包含数字2[1, 2, 3]含字符串2候选2匹配数字元素而[1, 2, 3]不包含字符串4嵌套结构{a: [1, 2], b: {c: 3}}包含{b: {c: 3}}嵌套对象逐层精确相等为真包含{a: [1]}数组元素不全为假[{a: 1}, {b: 2}]包含[{a: 1}]、{a: 1}、{a: 1, b: 2}分散对象均为真包含{a: 2}、{a: 1, b: 3}、{a: 1, b: 2, c: 3}为假非搜索式语义{x: {a: 1}}不包含{a: 1}[{x: {a: 1}}]不包含{a: 1}——明确验证了不做深层子树搜索的边界。这些用例与文档中的 6 个示例相互印证并补充了文档未展开的边界情况可作为编写生产查询时的行为参考。实际使用建议结合函数语义与源码行为给出以下实践建议配合 PARSE_JSON 构造候选候选值可直接用PARSE_JSON字面量构造例如判断某个 JSON 配置列是否包含enabled: trueSELECT * FROM t WHERE json_contains(config_col, PARSE_JSON({enabled: true}))利用对象子集语义做标签/属性匹配若目标是{os: linux, arch: x86, zone: a}之类的文档可用json_contains(target, PARSE_JSON({os: linux, zone: a}))实现多条件同时命中的过滤不必逐一取键比较数组场景注意元素精确性需要匹配数组中是否存在某个完整对象时直接可用需要匹配对象的部分字段时应先将数据转换为对象再比较或改用数组内元素展开后配合其他 JSON 函数处理处理 NULL 语义SQL NULL 输入会得到 NULL 输出过滤场景建议用WHERE json_contains(...) 1或IS TRUE明确排除 NULL 行性能视角该函数为向量化实现逐列逐行处理 常量折叠在过滤条件中直接使用即可对于超大 JSON 列包含判定是 O(候选键/元素数 × 目标键/元素数) 级别的扫描建议将高频过滤字段冗余为独立列以换取更高查询性能。总结json_contains是 StarRocks JSON 能力集中一个语义精确、边界清晰的基础函数对象按子集键值对判定数组按元素包含判定标量按相等判定且不做跨层级的递归搜索。文档中的 6 个示例、BE 端 JsonContainmentChecker 的递归实现以及 json_functions_test.cpp 中数十个参数化用例共同构成了理解该函数行为的完整证据链。在日志筛选、配置校验、半结构化数据匹配等场景中json_contains可以让你用一条简洁的 SQL 完成原本需要多层展开与比较的复杂判定。【免费下载链接】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),仅供参考
返回列表