BigQuery/Firebase 查询事件,按用户属性排序

Posted

技术标签:

【中文标题】BigQuery/Firebase 查询事件,按用户属性排序【英文标题】:BigQuery/Firebase querying events, order by User Property 【发布时间】:2016-10-19 08:08:36 【问题描述】:

我将我的 Firebase 项目连接到 BigQuery,并在今天收到了所有昨天的事件。

我有一个具有整数参数的用户定义事件。 以及字符串类型的用户属性“user_job”(例如“Pilot”、“Mechanic”、“Programmer”……) 我想知道按用户作业分组的整数参数的平均值。

是否有提取该信息的 SQL 查询?

我知道 SQL,但我的问题是数据以某种方式嵌套在 RECORD 中,我不知道如何处理。 如果每个事件是一行,每个用户属性是一列,我就不会有这个问题。如果是这样,我可以这样写:

SELECT AVG( param ), user_job FROM table WHERE event_type = "my_event" GROUP BY user_job

但用户属性位于 RECORD(数组?)内,并且 RECORD 内还有多个事件。

或者,使用 SQL 查询可能是处理此类请求的错误方法。如果是这样,有人可以指点我的方向。 我看到 BigQuery 中有 user defined functions。那么我是否应该创建一个用户定义的函数,将 Firebase BigQuery 行转换为上面写的平面结构,这是正确的方法吗?

更新: 我运行了来自 Sara 和 Elliot 的查询,并且在两种情况下处理的字节都相同(这是成本)。 Saras 查询比 Elliots 运行得更快,但这可能是随机的机会(而且 google 对数据收费,而不是时间)。 尽管如此,我还是将 Elliots 的答案标记为最终答案,因为根据文档,标准 SQL 是推荐的答案。 我仍然不知道这一切与 UDF 相比如何,可能会对其进行测试。

更新 2: 我使用 UDF 实现对其进行了测试,该实现为每个 round_completed 事件发出一个新行(语言、硬币)。与 Sara 和 Elliot 发布的纯 SQL 解决方案相比,它运行时间更长,处理的数据更多。

|_Solution___|_Time___|_Data Processed___|
|Sara        |2.1s    |399 KB            |
|Elliot      |2.4s    |399 KB            |
|UDF         |3.4s    |437 KB            |

*请注意,时间可能是一个不好的指标,因为不知道谷歌数据中心在给定时间的繁忙程度。最后,处理的数据越少,成本就越低。我还是把时间加进去了,也许有点用处。

【问题讨论】:

我现在使用用户定义的函数让它工作。循环遍历所有用户属性和所有事件。我不知道这是否正确,并会在月底看到它的成本。但它有效。 【参考方案1】:

我建议使用 standard SQL 而不是旧版 SQL 进行此类分析,因为它使语义更清晰。用户定义的函数,尤其是在旧版 SQL 中,将比仅使用 SQL 更难维护且成本更高。

这是一个可能有帮助的示例查询。要运行它,请取消选中 UI 中“显示选项”下的“使用旧版 SQL”:

SELECT
  user_properties.value.value.string_value as lang,
  AVG((SELECT SUM(value.int_value)
       FROM UNNEST(event_dim),
         UNNEST(params)
       WHERE key = "coins_awarded")) as avg_coins 
FROM 
  `firebase-analytics-sample-data.ios_dataset.app_events_20160607` t,
    UNNEST(user_dim.user_properties) user_properties
WHERE 
  user_properties.key = "language"
GROUP BY 1;

在此查询中,带有UNNEST(user_dim.user_properties) 的逗号运算符为重复的user_properties 中的每个元素返回一行:

`firebase-analytics-sample-data.ios_dataset.app_events_20160607`,
  UNNEST(user_dim.user_properties) user_properties

在计算所有重复的int_value之和的子查询中,UNNEST用于将重复的event_dimparams转换为行,逗号运算符取它们之间的叉积:

SELECT SUM(value.int_value)
FROM UNNEST(event_dim),
  UNNEST(params)
WHERE key = "coins_awarded"

有关旧版 SQL 中的 FLATTEN 和标准 SQL 中的等价物的更多信息,请参阅迁移指南中的 Removing repetition with FLATTEN

【讨论】:

【参考方案2】:

要完成此操作,您需要FLATTEN 重复字段之一。使用示例 Firebase Analytics datasets,这是一个查询,它的功能类似于您想要实现的目标:

SELECT
  user_dim.user_properties.value.value.string_value as lang,
  AVG(event_dim.params.value.int_value) as avg_coins 
FROM 
  FLATTEN([firebase-analytics-sample-data:ios_dataset.app_events_20160607], user_dim.user_properties)
WHERE 
  user_dim.user_properties.key = "language"
  AND event_dim.params.key = "coins_awarded"
GROUP BY 1

这将获得按用户的语言偏好分组的平均奖励硬币数量。

【讨论】:

我使用 UDF 让它工作,该 UDF 发出一个包含语言和 coin_awarded 的新行。如果您将其与 flatten 方法进行比较,您知道哪个更昂贵吗? 这对我来说还是有点奇怪,可以说 event_dim.params.key = "something",因为 event_dim.params 实际上是一个包含多个键的 RECORD。 这个答案非常好并且有效。我将 Elliot 的另一个答案标记为正确答案,因为根据文档,推荐使用标准 SQL。我对这两种解决方案都投了赞成票。

以上是关于BigQuery/Firebase 查询事件,按用户属性排序的主要内容,如果未能解决你的问题,请参考以下文章

无法按 BigQuery/Firebase 中的内容对购买者进行排序

Bigquery 中的自定义定义

如何改善数据流管道中的低吞吐量 groupbykey

robot常用命令

系统分析与设计——作业5

运行查询以从大查询中获取事件计数