我正在尝试使用 GCP 日志分析功能来获取日志记录存储桶中所有日志事件的详细信息。
我从日志存储桶数据集中查询的字段是:
log_name STRING
json_payload JSON
为了确保我使用所有
STRING
数据类型,我将需要的字段选择到临时表中并查询临时表。
WITH log_breakdown AS (
SELECT log_name,
STRING(json_payload['@type']) AS log_type
FROM myorg.global._Default._AllLogs
WHERE timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
)
根据下面的内容,所有字段的类型均为
STRING
。
SELECT * FROM log_breakdown
但是,如果我尝试按
log_type
进行分组,则会收到 Grouping by expressions of type STRUCT is not allowed
错误。
SELECT log_name,
log_type,
COUNT(log_type) AS event_count
FROM log_breakdown
GROUP BY (log_name, log_type)
ORDER BY event_count desc
如果临时表中的每个字段都是
STRING
类型,为什么我仍然会收到此错误?
如何聚合
log_type
来获取 json_payload 日志事件的详细信息?
正如 @Mikhail Berlyant 所提到的,这个问题可以通过使用
(log_name, log_type)
来解决,这使得它隐式地成为 struct 类型。您可以删除 (
和 )
并使用 GROUP BY log_name, log_type
。
不久前我遇到了同样的问题,一开始真的让我很失望。在 BigQuery 中,当您使用 JSON_EXTRACT 时,它会返回 JSON(或 STRUCT)格式的数据,该格式无法直接分组。本质上,BigQuery 将其视为结构化对象,而不是简单的字符串或数值。
一个快速修复方法是从 JSON_EXTRACT 切换到 JSON_VALUE,这会告诉 BigQuery 将字段解析为文本,而不是将其作为结构化数据返回。例如:
选择 JSON_VALUE(payload, "$.level") AS 级别, JSON_VALUE(payload, "$.message") AS 消息, 计数(*) AS c 来自你的表 按 1、2 分组
通过这样做,级别和消息就变成了纯字符串,并且按它们进行分组就可以了。如果您混合数字和字符串字段,您可能仍然需要将它们转换为正确的类型。但在大多数情况下,只需切换到 JSON_VALUE 即可立即解决分组问题。
希望这有帮助!如果您仍然遇到任何奇怪的情况,请告诉我。有时解析日志可能有点棘手,但是一旦掌握了 BigQuery 如何处理 JSON 字段,它就会变得更加顺利。