其他 JSON 建模的方法
以下是 ClickHouse 中建模 JSON 的替代方案。这些记录是为了完整性,一般不推荐或适用于大多数使用案例。
使用 Nested
Nested 类型 可用于建模静态对象,这些对象很少发生变化,提供了 Tuple
和 Array(Tuple)
的替代方案。我们通常建议避免将此类型用于 JSON,因为其行为通常令人困惑。Nested
的主要好处是子列可以用于排序键。
以下是使用 Nested 类型建模静态对象的示例。考虑以下简单的 JSON 日志条目:
我们可以将 request
键声明为 Nested
。类似于 Tuple
,我们需要指定子列。
flatten_nested
设置 flatten_nested
控制嵌套的行为。
flatten_nested=1
值为 1
(默认值)不支持任意等级的嵌套。使用此值,可以将嵌套数据结构视为多个同长度的 Array 列。字段 method
、path
和 version
实际上都是单独的 Array(Type)
列,并有一个关键限制:method
、path
和 version
字段的长度必须相同。 如果使用 SHOW CREATE TABLE
,将会表明这是:
下面,我们向此表插入数据:
需要注意的几点重要事项:
-
我们需要使用设置
input_format_import_nested_json
来插入嵌套结构的 JSON。否则,我们需要将 JSON 展平,即。 -
嵌套字段
method
、path
和version
需要作为 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
。