如何实现GraphQL连接的后端?

时间:2018-10-02 15:00:49

标签: sql sorting pagination graphql

在GraphQL中,建议的分页方法是使用here中所述的连接。我了解这种用法​​的原因和优点,但是我需要如何实施的建议。

应用程序的服务器端在SQL数据库(以我的情况为Postgres)之上工作。某些GraphQL连接字段具有用于指定排序的可选参数。现在了解了GraphQL查询中的排序列和游标后,如何构建SQL查询?当然,它应该是有效的-如果有SQL索引索引用于排序列的组合,则应使用它。

问题是SQL不知道像GraphQL游标那样的东西-我们不能告诉它选择特定行之后的所有行。只有WHERE,OFFSET和LIMIT。从我的角度来看,我似乎首先需要基于游标选择一行,然后使用该行中的排序列的值来构建第二个SQL查询以指定复杂的WHERE子句-不确定数据库是否会使用在这种情况下索引。

让我困扰的是我找不到有关此主题的任何文章。这是否意味着在实现GraphQL服务器时通常不使用SQL数据库?那应该使用什么数据库呢?通常,对连接字段的GraphQL查询如何转换为对基础数据库的查询?

编辑:This差不多是我自己想到的。问题在于如何扩展它以支持排序以及如何使用数据库索引有效地实现它。

1 个答案:

答案 0 :(得分:0)

这里的技巧是,作为服务器实现者,游标实际上可以是您想要编码为字符串的任何值。我见过的大多数示例都经过了base64编码,以实现一定程度的不透明性,但这不是必须的。 (例如,尝试通过base64解码链接中“星球大战”示例中的光标。)

假设您的GraphQL模式如下

enum ThingColumn { FOO BAR }
input ThingFilter {
  foo: Int
  bar: Int
}
type Query {
  things(
    filter: ThingFilter,
    sort: ThingColumn,
    first: Int,
    after: String
  ): ThingConnection
}

您的第一个查询可能是

query {
  things(filter: { foo: 1 }, sort: BAR, first: 2) {
    edges {
      node { bar }
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}

这本身可以相当直接地转换为SQL查询,例如

SELECT bar FROM things WHERE foo=1 ORDER BY bar ASC LIMIT 2;

现在,当您遍历每个项目时,只需使用其偏移量的字符串版本作为其光标即可;规范完全允许。

{
  "data": {
    "things": {
      "edges": [
        { "node": { "bar": 17 } },
        { "node": { "bar": 42 } }
      ],
      "pageInfo": {
        "endCursor": "2",
        "hasNextPage": true
      }
    }
  }
}

然后,当下一个查询显示after: "2"时,您可以将其转换回SQL OFFSET并重复查询。

如果您试图构建一个通用的GraphQL接口,该接口可以转换为合理的通用SQL查询,则不可能创建索引以使每个查询都“快速”。与其他情况一样,您需要弄清楚什么是常见查询和/或慢查询,并根据需要CREATE INDEX。您也许可以将架构中的选项限制为您知道可以索引的内容:

type Other {
  things(first: Int, after: String): ThingConnection
}
query OtherThings($id: ID!, $cursor: String) {
  node(id: $id) {
    ... on Other {
      things(first: 100, after: $cursor) { ... FromAbove }
    }
  }
}
SELECT * FROM things WHERE other_id=? ORDER BY id LIMIT ?;
CREATE INDEX things_other ON things(other_id);