跳到主要内容
跳到主要内容

其他 JSON 建模的方法

以下是 ClickHouse 中建模 JSON 的替代方案。这些记录是为了完整性,一般不推荐或适用于大多数使用案例。

使用 Nested

Nested 类型 可用于建模静态对象,这些对象很少发生变化,提供了 TupleArray(Tuple) 的替代方案。我们通常建议避免将此类型用于 JSON,因为其行为通常令人困惑。Nested 的主要好处是子列可以用于排序键。

以下是使用 Nested 类型建模静态对象的示例。考虑以下简单的 JSON 日志条目:

我们可以将 request 键声明为 Nested。类似于 Tuple,我们需要指定子列。

flatten_nested

设置 flatten_nested 控制嵌套的行为。

flatten_nested=1

值为 1(默认值)不支持任意等级的嵌套。使用此值,可以将嵌套数据结构视为多个同长度的 Array 列。字段 methodpathversion 实际上都是单独的 Array(Type) 列,并有一个关键限制:methodpathversion 字段的长度必须相同。 如果使用 SHOW CREATE TABLE,将会表明这是:

下面,我们向此表插入数据:

需要注意的几点重要事项:

  • 我们需要使用设置 input_format_import_nested_json 来插入嵌套结构的 JSON。否则,我们需要将 JSON 展平,即。

  • 嵌套字段 methodpathversion 需要作为 JSON 数组传递,即。

可以使用点表示法查询列:

请注意,子列使用 Array 意味着可以利用完整的 Array 函数,包括 ARRAY JOIN 子句 - 如果您的列有多个值,这将非常有用。

flatten_nested=0

这允许任意层次的嵌套,意味着嵌套列保持为单个 Tuple 的数组 - 实际上它们变为与 Array(Tuple) 相同。

这代表了首选的方法,也通常是使用 Nested 的最简单方法。如我们所示,只需确保所有对象是一个列表。

下面,我们重新创建表并重新插入一行:

需要注意的几点重要事项:

  • 不需要 input_format_import_nested_json 来插入。

  • SHOW CREATE TABLE 中保留了 Nested 类型。此列底层实际上是一个 Array(Tuple(Nested(method LowCardinality(String), path String, version LowCardinality(String))))

  • 因此,我们需要将 request 作为数组插入,即。

列再次可以使用点表示法查询:

示例

上述数据的更大示例可在 S3 的公共桶中找到:s3://datasets-documentation/http/

考虑到 JSON 的约束和输入格式,我们使用以下查询插入此示例数据集。在此,我们将 flatten_nested=0

以下语句插入 1000 万行,因此执行可能需要几分钟。如果需要,请应用 LIMIT

查询此数据需要访问请求字段作为数组。下面,我们总结在固定时间段内的错误和 HTTP 方法。

使用成对数组

成对数组在将 JSON 表示为字符串的灵活性和更结构化方法的性能之间提供了平衡。模式是灵活的,可以在根部潜在地添加任何新字段。然而,这需要显著更复杂的查询语法,并且不兼容嵌套结构。

例如,考虑以下表:

要向此表插入数据,我们需要将 JSON 结构化为键和值的列表。以下查询说明了使用 JSONExtractKeysAndValues 来实现这一点:

请注意,请求列以字符串表示的嵌套结构保持不变。我们可以将任何新键插入到根部。我们还可以在 JSON 本身中存在任意差异。要插入到我们的本地表中,请执行以下操作:

查询此结构需要使用 indexOf 函数来识别所需键的索引(这应与值的顺序一致)。这可以用来访问值数组列,即 values[indexOf(keys, 'status')]。我们仍然需要一种 JSON 解析方法来处理请求列 - 在这种情况下,使用 simpleJSONExtractString