Skip to content

使用 GraphQL API

数据墙DBW 自动为每个实体生成 GraphQL 架构。所有请求通过 POST 发送到 /graphql 端点,查询内容写在请求体的 query 字段中。

端点与请求格式

http
POST http://localhost:5000/graphql
Content-Type: application/json

{
  "query": "{ books { items { id title } } }"
}

GraphQL 端点始终使用 POST,即使只是查询数据。变量可以分离到 variables 字段中。

查询列表

curl

bash
curl -X POST http://localhost:5000/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "{ books { items { id title year pages } } }"}'

JavaScript

javascript
const res = await fetch("http://localhost:5000/graphql", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    query: "{ books { items { id title year pages } } }"
  }),
});
const data = await res.json();
console.log(data.data.books.items);

Python

python
import requests
res = requests.post("http://localhost:5000/graphql",
  json={"query": "{ books { items { id title year pages } } }"})
data = res.json()
for item in data["data"]["books"]["items"]:
    print(item)

响应格式

json
{
  "data": {
    "books": {
      "items": [
        { "id": 1, "title": "示例图书", "year": 2023, "pages": 300 }
      ],
      "hasNextPage": false,
      "endCursor": null
    }
  }
}

GraphQL 响应嵌套在 data.{实体名}.items 中。分页字段 hasNextPageendCursor 始终出现。

按主键查询

graphql
{
  book_by_pk(id: 1) {
    id
    title
    year
  }
}

如果主键不存在,GraphQL 返回错误而不是空数据:

json
{
  "errors": [
    {
      "message": "Could not find item with the given key.",
      "path": ["book_by_pk"]
    }
  ]
}

使用变量

变量将查询结构与参数值分离,避免字符串拼接:

graphql
query GetBook($id: Int!) {
  book_by_pk(id: $id) {
    id
    title
    year
  }
}
json
{
  "query": "query GetBook($id: Int!) { book_by_pk(id: $id) { id title } }",
  "variables": { "id": 1 }
}

JavaScript 示例

javascript
const query = `
  query GetBook($id: Int!) {
    book_by_pk(id: $id) { id title year }
  }
`;
const res = await fetch("http://localhost:5000/graphql", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ query, variables: { id: 1 } }),
});

筛选与排序

GraphQL 使用 filterorderBy 参数,语法与 REST 不同——使用对象嵌套而非 URL 查询字符串:

graphql
{
  books(
    filter: { year: { ge: 2000 }, pages: { gt: 300 } }
    orderBy: { year: DESC, title: ASC }
  ) {
    items { id title year pages }
  }
}

筛选运算符

eq        等于    { title: { eq: "Dune" } }
neq       不等于  { year: { neq: 2000 } }
gt        大于    { pages: { gt: 300 } }
gte       大于等于 { year: { gte: 2000 } }
lt        小于    { pages: { lt: 100 } }
lte       小于等于 { year: { lte: 2020 } }
contains  包含    { title: { contains: "Foundation" } }
isNull    为空    { deleted_at: { isNull: true } }

逻辑组合:

graphql
{
  books(
    filter: {
      or: [
        { year: { gt: 2000 } }
        { title: { contains: "Dune" } }
      ]
    }
  ) { items { id title } }
}

分页

graphql
{
  books(first: 5) {
    items { id title }
    hasNextPage
    endCursor
  }
}

翻到下一页:

graphql
{
  books(first: 5, after: "eyJpZCI6NX0=") {
    items { id title }
    hasNextPage
    endCursor
  }
}

创建记录

graphql
mutation {
  createBook(item: { id: 100, title: "新书", year: 2024, pages: 280 }) {
    id
    title
    year
  }
}

变量形式:

graphql
mutation CreateBook($item: CreateBookInput!) {
  createBook(item: $item) { id title year }
}
json
{
  "variables": {
    "item": { "id": 100, "title": "新书", "year": 2024, "pages": 280 }
  }
}

IMPORTANT

GraphQL 变更(mutation)需要数据库连接池启用多活动结果集。SQL Server 用户请确保连接字符串包含 MultipleActiveResultSets=True。连接池配置 Pooling=False 可能导致变更操作失败。

更新记录

graphql
mutation {
  updateBook(id: 100, item: { title: "更新后的书名" }) {
    id
    title
  }
}

只传递需要更新的字段,未传递的字段保持原值。

删除记录

graphql
mutation {
  deleteBook(id: 100) {
    id
    title
  }
}

链式变更

可以在一个请求中执行多个不同类型的变更操作:

graphql
mutation {
  book1: createBook(item: { id: 101, title: "第一本" }) { id title }
  book2: updateAuthor(id: 10, item: { lastName: "更新后的姓" }) { id lastName }
}

多个变更按顺序执行,互不影响。需要使用别名(book1:book2:)区分同名或不同类型的操作。

IMPORTANT

链式变更不支持事务——某个操作失败时已执行的操作不会回滚。客户端需要同时检查 dataerrors 来确认每个操作的结果。

NOTE

批量创建(items: [...] 数组形式)需要额外配置 runtime.graphql.multiple-mutations.create.enabled: true,详见GraphQL 多重变更。链式变更(使用别名)不需要该配置。多重创建仅 SQL Server 支持。

错误处理

GraphQL 错误统一在 errors 数组中返回:

json
{
  "data": null,
  "errors": [
    {
      "message": "Could not find item with the given key.",
      "path": ["book_by_pk"]
    }
  ]
}

部分成功时 dataerrors 可能同时存在:

json
{
  "data": { "book_by_pk": null },
  "errors": [{ "message": "..." }]
}

客户端需要同时检查 dataerrors 来确认每个操作的结果。

错误处理(JavaScript)

javascript
const res = await fetch("http://localhost:5000/graphql", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ query }),
});
const { data, errors } = await res.json();
if (errors?.length) console.error(errors[0].message);

字段别名

在查询中可以为字段指定别名:

graphql
{
  books {
    items {
      bookId: id
      bookTitle: title
    }
  }
}

响应中字段名将使用别名:

json
{ "bookId": 1, "bookTitle": "示例图书" }

架构内省

GraphQL 端点默认支持内省,客户端可以自动发现所有可用的查询、变更和类型。使用支持 GraphQL 的客户端(Apollo Studio、Postman、Insomnia)连接 /graphql 即可浏览完整架构。

生产环境可通过 runtime.graphql.allow-introspection: false 关闭内省。

下一步

数据墙DBW 产品文档与开发指南。