GraphQL 中聚合函数的支持
Posted
技术标签:
【中文标题】GraphQL 中聚合函数的支持【英文标题】:Support of aggregate function in GraphQL 【发布时间】:2016-05-04 08:05:35 【问题描述】:我对 GraphQL 的分析解决方案非常感兴趣(想想显示图表的 web 应用程序)。但我找不到任何使用聚合函数的 GraphQL 示例。这是我的前端完成的大多数查询的主要方面。
对于我的解决方案,我们有 3 个典型的后端调用。
-
搜索
聚合
时间序列
假设我们在 GraphQL 中指定了这种类型
type Person
name: String
age: Int
create_time: Date
-
搜索
这似乎被 GraphQL 处理得很好。这里没有问题。
例如。搜索名为 Bob 的人的年龄 人(姓名:“鲍勃”) 年龄
-
聚合
这是我想在饼图中显示信息的典型情况。所以假设我想按年龄计算人数。
这里是 PostgreSQL 查询:
SELECT age, count(*) from Ticket group by age;
GraphQL 中的等价物是什么?
-
时间序列
这是我想在条形图中显示信息的典型情况,X 轴为时间。
例如。假设我想统计每小时创建的用户数。
这里是 PostgreSQL 查询:
SELECT date_trunc('hour', create_time) as create_time_bin, count(*) from Person group by create_time_bin order by create_time_bin ASC;
GraphQL 等效查询是什么?
【问题讨论】:
更不用说,您如何对标量进行范围比较,例如 SELECT * WHERE timestamp > ... AND timestamp 您将参数添加到允许该类型过滤的字段。 【参考方案1】:GraphQL 最终会以您定义的类型进行响应。您只需要将这些数据放入一个类型中。无论这是针对这些不同查询的特定类型,还是针对现有类型的该数据的字段,这取决于您,但归根结底就是这些。 GraphQL 在定义类型和所有查询将返回什么方面确实需要更多的努力,这使得它更加僵化,但想法是另一方面还有一些很酷的特性,比如自省和类型检查。如果将这种“临时”数据结构放入 GraphQL 类型似乎没有逻辑意义,那么如果您需要其他数据源,使用非 GraphQL 端点并不违法。
【讨论】:
我想我明白你在说什么,但我明白这个实现的样子。 @Damien,每个 GraphQL 查询都由 resolve() 函数响应。您提供给查询的查询参数是此函数的参数。 resolve() 函数然后消失并执行您想要的任何操作,例如从其他地方检索 SQL 查询的结果,然后您可以根据需要聚合该数据,最后返回所有结果作为您对 GraphQL 查询的响应.要点是:您应该像 resolve() 只是另一个返回数字的 JS 函数一样进行聚合。但是查询的客户端不需要知道或关心。【参考方案2】:@Damien,这些问题不是 GraphQL 的问题。
当你想在 GraphQL 中做某事时,你必须定义一个返回数据的类型、你实现的函数的规格,有时还有一个输入数据的类型 输入你的函数。最后你编写代码来完成这项工作。
事实上,看起来您(重新)用 GraphQL 语言编写代码。
以你想在饼图中显示信息为例:
SELECT age, count(*) from Ticket group by age;
在此处定义您的退货数据是年龄和计数列表:
type TickGroupByAge
age: Int
count: Int
用 GraphQL 语言定义您的函数或查询:
getTicketGroupByAge : [TickGroupByAge]`
最后写一个函数来实现上面的查询:
async function()
const res = await client.query("SELECT age, count(*) from Ticket group by age");
return res.rows;
@Ryan 我完全同意你的观点,GraphQL 强迫你编写大量类型定义来解决一个简单的任务。出于这个原因,我最终构建了自己的 NextQL - GraphQL-liked engine,它类似于 GraphQL,但更简单。
我的项目支持复杂的嵌套类型定义,让你免于定义很多无用的类型。
【讨论】:
除了挑剔之外,我看不出在建议类型“TickGroupByAge”中将“Ticket”缩短为“Tick”的意义。它损害了可读性,而且字符很便宜。【参考方案3】:查看https://github.com/niclasko/Cypher.js(注:我是作者)
与问题相关。它可用于查询和聚合来自 JSON 端点的数据:
load json from "http://url/person" as l return l.age, count(1)
甚至还有条形图功能:
load json from "http://url/person" as l return barchart(toint(l.age)) as age_distribution
这是一个查询复杂 JSON 文档并对其执行聚合分析的示例:
Cypher.js JSON query example
【讨论】:
以上是关于GraphQL 中聚合函数的支持的主要内容,如果未能解决你的问题,请参考以下文章
django的聚合函数和aggregateannotate方法使用
从 PostgreSQL 到 Cassandra - 不支持聚合函数