ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OneUptime API 查询操作符 GreaterThanOrNull 详解:请求格式、语义边界与数据库层实现

OneUptime API 查询操作符 GreaterThanOrNull 详解:请求格式、语义边界与数据库层实现 OneUptime API 查询操作符 GreaterThanOrNull 详解请求格式、语义边界与数据库层实现【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptimeGreaterThanOrNull 是 OneUptime 开放 API 中用于构造查询条件的操作符之一它匹配字段值大于指定值或者该字段为 NULL的记录。本文以 API 参考文档中的示例为起点结合仓库源码逐层剖析该操作符的 JSON 请求格式、序列化机制、PostgreSQL 与 ClickHouse 两侧的 SQL 生成逻辑并给出可验证的测试依据帮助你在调用 OneUptime 查询 API或为自定义字段编写过滤条件时准确使用这一语义。操作符语义比大于多覆盖一类记录在 OneUptime 的 API 参考文档中GreaterThanOrNull的官方定义是A query filter that matches objects where a field is greater than the specified value or is null.参见 DataTypes.ts 中的类型注册表。也就是说它等价于 SQL 中的field value OR field IS NULL。与普通的GreaterThan仅匹配field value相比它额外把该字段没有值的记录也纳入结果集。这一语义在两类场景下尤为关键稀疏数据的统计查询例如监控事件中某字段尚未被采集端填充为 NULL但你希望这类记录仍然出现在字段值大于阈值的过滤结果里而不是被静默丢弃自定义字段custom fields过滤项目中的自定义字段并非每行记录都会填写使用GreaterThanOrNull可以保证未填写的行与填写且超过阈值的行同时命中。请求格式一个 JSON 片段即可表达API 参考文档中给出的示例原文档位于 GreaterThanOrNull.md是一个可直接放入查询体query字段的 JSON 对象{ query: { age: { _type: GreaterThanOrNull, value: 10 } } }其中字段类型说明query对象查询条件容器键为字段名值为该字段的条件表达式age字段名被过滤的目标字段可以是模型上的普通列也可以是 jsonb 自定义字段_type字符串操作符类型标识固定为GreaterThanOrNull服务端据此反序列化为对应的操作符实例valuenumber / Date / string比较基准值下例为10表示age 大于 10 或 age 为 NULLvalue的合法类型由CompareType约束为number | Date | string定义见 CompareBase.ts。因此下面的写法同样合法{ query: { createdAt: { _type: GreaterThanOrNull, value: 2026-01-01T00:00:00.000Z } } }序列化与反序列化客户端到服务端的类型往返GreaterThanOrNull在 TypeScript 侧是一个继承自CompareBaseT的值对象类核心实现位于 GreaterThanOrNull.tstoJSON()返回{ _type: GreaterThanOrNull, value: 原始值 }。这里刻意携带原始值而非toString()的结果因为toString()对Date会调用asDateForDatabaseQuery在本地时区将日期折叠为仅日期字符串导致从浏览器发出的查询边界最多偏移一天而JSON.stringify会把原始Date渲染为完整 ISO 时间戳服务端能以全精度绑定参数。这一点在类内的注释以及测试 GreaterThanOrNull.test.ts 中均有明确说明。toString()对Date值会先经OneUptimeDate.asDateForDatabaseQuery归一化后再输出字符串用于服务端生成 SQL 时的参数文本。fromJSON()校验_type必须等于GreaterThanOrNull否则抛出BadDataException见 GreaterThanOrNull.ts保证反序列化不静默接受非法输入。服务端转换QueryUtil 如何识别并翻译该操作符请求到达服务端后查询构建器会遍历query中的每个键并在 QueryUtil.ts 中识别GreaterThanOrNull实例} else if ( query[key] query[key] instanceof GreaterThanOrNull tableColumnMetadata ) { query[key] QueryHelper.greaterThanOrNull( (query[key] as LessThanOrNullCompareType).toString() as any, ) as any; }随后调用 QueryHelper.ts 中的greaterThanOrNull生成 SQL 片段return Raw( (alias: string) { return (${alias} :${rid} or ${alias} IS NULL); }, { [rid]: value }, ) as FindWherePropertyany;可以看到普通关系列上的最终 SQL 语义正是(列 :value or 列 IS NULL)参数通过随机命名的绑定参数传入避免直接拼接用户输入。CaptureSpan()装饰器同时为该操作接入链路追踪便于在 OneUptime 可观测体系中定位慢查询。jsonb 自定义字段场景更复杂的组合谓词当目标字段位于 jsonb 列例如customFields内部时GreaterThanOrNull走的是另一条独立的执行路径。在 JSONColumnQuery.ts 中if (value instanceof GreaterThanOrNull) { return this.join( [this.compareNumeric(, value.value), this.isEmpty()], OR, ); }这段代码揭示了两个值得注意的实现细节数值比较受类型保护。jsonb 键对应的值是什么类型只有运行时才知道因此比较前会通过numericExpression把值包进一个CASE WHEN仅当文本匹配^\s*-?[0-9](\.[0-9])?\s*$可选符号的十进制数见 JSONColumnQuery.ts时才执行CAST(... AS NUMERIC)否则返回NULL。这避免了CAST(abc AS NUMERIC)直接中止整条查询的隐患。空是一组并集条件。isEmpty()将以下四种情况统一视为字段为空JSONColumnQuery.ts键缺失col - key IS NULL显式 JSONnull空字符串空数组多选框清空后遗留的[]。因此在 jsonb 列上GreaterThanOrNull实际表达为数值阈值或键缺失、为 null、为空串、为空数组的析取。此外该模块还设有查询防护上限单次 JSON 列过滤最多携带 50 个键、每个键最多匹配 200 个值、键名最长 500 字符JSONColumnQuery.ts超出即返回 400防止手工构造的超大请求拖垮数据库。ClickHouse 分析库场景统一的操作符词汇表OneUptime 的时序/分析类模型AnalyticsModels查询经由 ClickHouse 路径执行。在 Statement.ts 中GreaterThanOrNull与LessThan、GreaterThan、LessThanOrNull等一起被识别为比较型操作符其value被直接提取用于后续 SQL 参数绑定} else if ( v.value instanceof LessThan || v.value instanceof LessThanOrEqual || v.value instanceof GreaterThan || v.value instanceof GreaterThanOrEqual || v.value instanceof LessThanOrNull || v.value instanceof GreaterThanOrNull || v.value instanceof NotEqual ) { finalValue v.value.value; }而语句生成器 StatementGenerator.ts 则把操作符翻译为 ClickHouse 的 WHERE 谓词并在对应属性路径上叠加IS NULL分支。从源码结构看这套标准列PostgreSQL jsonb 列PostgreSQL 分析列ClickHouse三路并行的实现正是为了确保同一组过滤条件在产品内不同数据源上读出一致的结果。测试验证行为契约的硬性保证仓库为GreaterThanOrNull提供了独立单元测试 GreaterThanOrNull.test.ts覆盖以下行为契约以合法值构造对象并读写valuetoString()输出原始值的字符串形式42→42toJSON()输出{ _type: GreaterThanOrNull, value: 42 }即携带原始数值而非字符串Date 值保留完整时间戳new Date(2026-07-21T14:35:12.345Z)经JSON.stringify(obj.toJSON())后仍为2026-07-21T14:35:12.345Z验证了旧实现把 Date 折叠成本地时区日期导致查询边界偏移一天这一缺陷已修复fromJSON()对合法输入正确还原实例对_type错误的输入抛出BadDataException。此外在 JSONColumnQuery.test.ts 与 CompareOperatorWireSerialization.test.ts 中也有该操作符参与 jsonb 谓词构建与线格式序列化往返的覆盖保证它与其他比较操作符共享同一套可序列化协议。与其他操作符的取舍对比在 API 参考文档的 DataTypes 目录下DataTypesGreaterThanOrNull与一组同族操作符并列存在选择时可以参考以下边界操作符语义匹配条件典型用途GreaterThan字段值阈值严格大于GreaterThanOrEqual字段值阈值含边界的大于GreaterThanOrNull字段值阈值或字段为 NULL稀疏字段的超过阈值或未填写LessThanOrNull字段值阈值或字段为 NULL稀疏字段的低于阈值或未填写EqualToOrNull字段值值或字段为 NULL稀疏字段的精确匹配或未填写IsNull/NotNull字段为空 / 非空单独判断空值需要说明的一个实现细节是在普通关系列上QueryHelper.greaterThanOrNull生成的谓词是严格大于而在 jsonb 自定义字段列上JSONColumnQuery对GreaterThanOrNull使用的是数值比较。两种数据路径下的严格/非严格差异以当前仓库源码为准编写跨数据源一致的过滤逻辑时应留意这一行为。小结GreaterThanOrNull是 OneUptime 查询协议中带空值兜底的一类比较操作符请求侧只需一个_typevalue的 JSON 片段服务端则会依据目标列的类型普通列、jsonb 自定义字段、ClickHouse 分析列分别生成对应的 SQL 谓词并通过绑定参数、数值类型保护和查询上限等手段保证安全性与稳定性。配合 GreaterThanOrNull.test.ts 中的行为契约你可以放心地在监控、事件与自定义字段过滤场景中使用该操作符让未填写的记录不再从查询结果中丢失。【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表