OpenCRUD

Working Draft – April 2018

介绍

TBD

1概述

OpenCRUD是一种完全兼容GraphQL compliant的查询语言,用于访问和修改数据。OpenCRUD为许多流行的数据库提供API风格,包括MySQL和MongoDB。

例如,此OpenCRUD查询检索单个用户:

{
  user(where: { id: 4 }) {
    name
  }
}

returns:

{
  "user": {
    "name": "Mark Zuckerberg"
  }
}

1.1依据

GraphQL是一种灵活的查询语言,支持许多不同的数据访问模式。实际上,简单的CRUD操作是一种非常常见的模式。标准化这种非常常见的模式使社区能够构建特定于常见CRUD样式API的工具。

1.2参考实现

Prisma 是OpenCRUD的参考实现

2关系

2.1覆盖的领域

该规范描述了适用于关系数据库的灵活GraphQL API的所有方面

2.2关注api,不包含实现以及运行时的特性

OpenCrud是GraphQL API的规范集合,旨在与特定的数据库技术配合使用。OpenCRUD关注API表面,而不是实现。因此,OpenCRUD的两个实现可以选择以不同的方式存储数据,但是通过OpenCRUD API与数据交互的应用程序将无法区分。

2.3SDL

本规范中使用的示例显示了为特定数据模型生成的最终模式。在所有示例中,SDL表示法用于定义数据模型。SDL的好处在于它与数据库无关,因此我们可以在所有支持的数据库中使用相同的表示法。

在本规范的示例SDL中使用时,以下指令具有特殊含义:

2.4Queries

2.4.1Queries: 顶级

  • 概述
  • 单字段多字段
  • 多连接字段
  • 节点字段
  • 例子
2.4.1.1概述

GraphQL定义顶级Query类型。OpenCRUD定义了为每种数据库类型生成的多个顶级字段(关系数据库中的表) s

2.4.1.2单字段

检索单个数据记录。

2.4.1.3多字段

检索多个数据记录

2.4.1.4多连接字段

检索多个数据记录。此字段兼容Relay compliant,同时包含子字段aggregategroupBy子字段。

2.4.1.5节点字段

节点字段由Relay spec规范指定,并允许客户端通过其id检索任何数据记录。

2.4.1.6命名

OpenCRUD未指定必须如何命名为每种数据类型生成的字段。由每个OpenCRUD实现决定一个命名系统。参考实现使用followig命名约定:

  • 单字段: [data type name]
  • 多字段: [pluralized data type name] (using the evo‐inflector library)
  • 多连接字段:[pluralized data type name]Connection

OpenCRUD实现可以选择使字段名称可配置而不是基于约定。

2.4.1.7示例

此示例说明了所有顶级字段

数据模型

type User {
  id: ID! @unique
  name: String!
}

生成的schema

type Query {
  users(
    where: UserWhereInput
    orderBy: UserOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ): [User]!
  user(where: UserWhereUniqueInput!): User
  usersConnection(
    where: UserWhereInput
    orderBy: UserOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ): UserConnection!
  node(id: ID!): Node
}

Query

query {
  user(where: { id: "1" }) {
    name
  }
  users(where: { name_contains: "Karl" }) {
    name
  }
  usersConnection(where: { name_contains: "Karl" }) {
    edges {
      node {
        name
      }
    }
  }
  node(id: "1") {
    name
  }
}

2.4.2Queries: 关系

  • 概述
  • 连接
    • 聚合
    • 游标
  • 实例
2.4.2.1概述

In relational databases a relation is used to connecto two related tables. OpenCRUD defines how relations are exposed in the GraphQL schema. Relations in OpenCRUD generate two fields: 在关系数据库中,关联用于连接两个相关表。OpenCRUD定义了如何暴露在GraphQL schema 关联。OpenCRUD中的关联生成两个字段:

  • multi fields 适用于需要检索相关数据的大多数情况
  • multi connection fields 与Relay兼容并包含支持avdanced聚合的aggrete和groupBy字段。
2.4.2.2连接

> WIP

2.4.2.3实例

此示例说明了所有顶级字段

数据模型

type User {
  id: ID! @unique
  name: String!
  posts: [Post!]!
}

type Post {
  id: ID! @unique
  title: String!
}

生成的schema

type User implements Node {
  id: ID!
  name: String!
  posts(
    where: PostWhereInput
    orderBy: PostOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ): [Post!]
  postsConnection(
    where: PostWhereInput
    orderBy: PostOrderByInput
    skip: Int
    after: String
    before: String
    first: Int
    last: Int
  ): PostConnection!
}

type Post implements Node {
  id: ID!
  title: String!
}

Query

query {
  user(where: {id: "1"}) {
    name
    posts {
      title
    }
    postsConnection {
      edges {
        node {
          title
        }
      }
    }
  }
}

2.4.3Queries: 过滤器

  • 概述
  • 数据类型
  • 单字段
  • 多字段
  • 布尔表达式
  • 交叉关系过滤器
2.4.3.1概述

OpenCRUD过滤器旨在尽可能多地显示底层数据库的功能,同时保持简单直观的API接口。过滤器可用于所有顶级字段和关系字段。

2.4.3.2数据类型

可用的过滤器取决于字段的类型。例如,Integer字段支持大于过滤器,而String字段支持在子字符串上匹配的contains过滤器。

type UserWhereInput {
  AND: [UserWhereInput]
  OR: [UserWhereInput]

  # String field
  field: String # equals
  field_not: String # not equals
  field_contains: String # contains substring
  field_not_contains: String # does not contain substring
  field_starts_with: String
  field_not_starts_with: String
  field_ends_with: String
  field_not_ends_with: String
  field_lt: String # less than
  field_lte: String # less then or equals
  field_gt: String # greater than
  field_gte: String # greater than or equals
  field_in: [String] # in list
  field_not_in: [String] # not in list

  # Integer field
  field: Integer # equals
  field_not: Integer # not equals
  field_lt: Integer # less than
  field_lte: Integer # less then or equals
  field_gt: Integer # greater than
  field_gte: Integer # greater than or equals
  field_in: [Integer] # in list
  field_not_in: [Integer] # not in list
  
  # Float field
  field: Float # equals
  field_not: Float # not equals
  field_lt: Float # less than
  field_lte: Float # less then or equals
  field_gt: Float # greater than
  field_gte: Float # greater than or equals
  field_in: [Float] # in list
  field_not_in: [Float] # not in list
  
  # Boolean field
  field: Boolean # equals
  field_not: Boolean # not equals
  
  # DateTime field
  field: DateTime # equals
  field_not: DateTime # not equals
  field_in: [DateTime] # in list
  field_not_in: [DateTime] # not in list
  field_lt: DateTime # less than
  field_lte: DateTime # less then or equals
  field_gt: DateTime # greater than
  field_gte: DateTime # greater than or equals
  
  # Enum field
  field: Enum # equals
  field_not: Enum # not equals
  field_in: [Enum] # in list
  field_not_in: [Enum] # not in list
  
  # List[T] field
  field_contains: T # contains single scalar T
  field_contains_every: [T] # contains all scalar T
  field_contains_some: [T] # contains at least 1 scalar T
 
  # many Relation field
   field_every: FilterCondition # condition must be true for all nodes
  field_some: FilterCondition # condition must be true for at least 1 node
  field_none: FilterCondition # condition must be false for all nodes
  field_is_null: Boolean # is the relation field null
 
  # one Relation field
  field: UserWhereInput # condition must be true for related node
}
2.4.3.3单字段

与单个数据记录关系的字段允许您按唯一字段上的完全匹配进行过滤:

{
  user(where: {id: "1"}){
    name
  }
}
2.4.3.4多字段

与许多数据记录关系的字段允许按上面指定的所有过滤器进行过滤:

{
  users(where: {name_not_in:["Karl", "Viggo"]}){
    name
  }
}
2.4.3.5布尔表达式

过滤条件可以嵌套,并使用布尔表达式组合任意ANDOR

{
  users(where: {OR: [
    {name_not_in: ["Karl", "Viggo"]},
  	{AND: [{id: "1"}, {name: "Karl"}]}
  ]}) {
    name
  }
}

同一级别的两个过滤条件是显式的AND,因此上面的查询可以简化为:

{
  users(where: {OR: [
    {name_not_in: ["Karl", "Viggo"]},
  	{id: "1", name: "Karl"}
  ]}) {
    name
  }
}
2.4.3.6交叉关系过滤器

在关系数据库中,通常基于相关表中的列进行过滤。在OpenCRUD中,这个概念称为关系过滤器。以下查询检索与具有id的帖子相关的所有用户1

{
  users(where:{posts_some:{id: "1"}}){
    name
  }
}

通过反向查询可以实现相同的结果:

{
  post(where: {id: "1"}) {
    author {
      name
    }
  }
}

关系过滤器与普通过滤器具有相同的功能,可以使用树修改器之一:

  • every
  • none
  • some
{
  every: users(where:{posts_every:{id: "1"}}){name}
  none: users(where:{posts_none:{id: "1"}}){name}
  some: users(where:{posts_some:{id: "1"}}){name}
}

2.4.4Queries: 聚合

  • 概述
  • 聚合函数
    • avg
    • median
    • max
    • min
    • count
    • sum
  • 分组
  • 实例: 组合 groupBy and Aggregations

> WIP. see https://github.com/graphcool/prisma/issues/1312

2.5Mutations

2.5.1Mutations: CRUD

  • 概述
  • Create
  • Update
  • Delete
2.5.1.1概述

OpenCRUD暴露以下mutations以进行简单的数据操作

2.5.1.2Create

创建单个数据racord:

mutation {
  createUser(data: { name: "Karl" }) {
    id
  }
}
2.5.1.3Update
mutation {
  updateUser(where: { id: "1" }, data: { name: "Karl" }) {
    id
  }
}
2.5.1.4Delete
mutation {
  deleteUser(where: { id: "1" }) {
    id
  }
}

2.5.2Mutationa: 批量操作

  • 概述
  • Update
  • Delete
2.5.2.1概述

OpenCRUD暴露了如下mutations以操纵一批数据记录。count字段返回受影响的记录数

2.5.2.2Update
mutation {
  updateManyUsers(where: {name_not: "Karl"}, data:{name: "Karl"}) {
    count
  }
}
2.5.2.3Delete
mutation {
  deleteManyUsers(where: {name_not: "Karl"}) {
    count
  }
}

2.5.3Mutations: 嵌套

2.5.3.1Overview

OpenCRUD嵌套mutations是一种操纵关系数据的强大方法。

> WIP. See https://github.com/graphcool/prisma/issues/1280

  1. 1概述
    1. 1.1依据
    2. 1.2参考实现
  2. 2关系
    1. 2.1覆盖的领域
    2. 2.2关注api,不包含实现以及运行时的特性
    3. 2.3SDL
    4. 2.4Queries
      1. 2.4.1Queries: 顶级
        1. 2.4.1.1概述
        2. 2.4.1.2单字段
        3. 2.4.1.3多字段
        4. 2.4.1.4多连接字段
        5. 2.4.1.5节点字段
        6. 2.4.1.6命名
        7. 2.4.1.7示例
      2. 2.4.2Queries: 关系
        1. 2.4.2.1概述
        2. 2.4.2.2连接
        3. 2.4.2.3实例
      3. 2.4.3Queries: 过滤器
        1. 2.4.3.1概述
        2. 2.4.3.2数据类型
        3. 2.4.3.3单字段
        4. 2.4.3.4多字段
        5. 2.4.3.5布尔表达式
        6. 2.4.3.6交叉关系过滤器
      4. 2.4.4Queries: 聚合
    5. 2.5Mutations
      1. 2.5.1Mutations: CRUD
        1. 2.5.1.1概述
        2. 2.5.1.2Create
        3. 2.5.1.3Update
        4. 2.5.1.4Delete
      2. 2.5.2Mutationa: 批量操作
        1. 2.5.2.1概述
        2. 2.5.2.2Update
        3. 2.5.2.3Delete
      3. 2.5.3Mutations: 嵌套
        1. 2.5.3.1Overview