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 - 不支持聚合函数

聚合初始化不支持构造函数访问[重复]

如何使用单个 SQL 聚合函数查询为同一个聚合函数获取多个结果?

60种特征工程操作:使用自定义聚合函数

37.12. User-Defined Aggregates