Working Draft – April 2018
介绍
TBD
OpenCRUD是一种完全兼容GraphQL compliant的查询语言,用于访问和修改数据。OpenCRUD为许多流行的数据库提供API风格,包括MySQL和MongoDB。
例如,此OpenCRUD查询检索单个用户:
{
user(where: { id: 4 }) {
name
}
}
returns:
{
"user": {
"name": "Mark Zuckerberg"
}
}
GraphQL是一种灵活的查询语言,支持许多不同的数据访问模式。实际上,简单的CRUD操作是一种非常常见的模式。标准化这种非常常见的模式使社区能够构建特定于常见CRUD样式API的工具。
Prisma 是OpenCRUD的参考实现
该规范描述了适用于关系数据库的灵活GraphQL API的所有方面
OpenCrud是GraphQL API的规范集合,旨在与特定的数据库技术配合使用。OpenCRUD关注API表面,而不是实现。因此,OpenCRUD的两个实现可以选择以不同的方式存储数据,但是通过OpenCRUD API与数据交互的应用程序将无法区分。
本规范中使用的示例显示了为特定数据模型生成的最终模式。在所有示例中,SDL表示法用于定义数据模型。SDL的好处在于它与数据库无关,因此我们可以在所有支持的数据库中使用相同的表示法。
在本规范的示例SDL中使用时,以下指令具有特殊含义:
@unique
:该字段具有唯一约束@relation
:指定两个字段之间的关系GraphQL定义顶级Query
类型。OpenCRUD定义了为每种数据库类型生成的多个顶级字段(关系数据库中的表) s
检索单个数据记录。
检索多个数据记录
检索多个数据记录。此字段兼容Relay compliant,同时包含子字段aggregate
和groupBy
子字段。
节点字段由Relay spec规范指定,并允许客户端通过其id检索任何数据记录。
OpenCRUD未指定必须如何命名为每种数据类型生成的字段。由每个OpenCRUD实现决定一个命名系统。参考实现使用followig命名约定:
[data type name]
[pluralized data type name]
(using the evo‐inflector library)[pluralized data type name]Connection
OpenCRUD实现可以选择使字段名称可配置而不是基于约定。
此示例说明了所有顶级字段
数据模型
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
}
}
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字段。> WIP
此示例说明了所有顶级字段
数据模型
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
}
}
}
}
}
OpenCRUD过滤器旨在尽可能多地显示底层数据库的功能,同时保持简单直观的API接口。过滤器可用于所有顶级字段和关系字段。
可用的过滤器取决于字段的类型。例如,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
}
与单个数据记录关系的字段允许您按唯一字段上的完全匹配进行过滤:
{
user(where: {id: "1"}){
name
}
}
与许多数据记录关系的字段允许按上面指定的所有过滤器进行过滤:
{
users(where: {name_not_in:["Karl", "Viggo"]}){
name
}
}
过滤条件可以嵌套,并使用布尔表达式组合任意AND
和OR
:
{
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
}
}
在关系数据库中,通常基于相关表中的列进行过滤。在OpenCRUD中,这个概念称为关系过滤器。以下查询检索与具有id的帖子相关的所有用户1
。
{
users(where:{posts_some:{id: "1"}}){
name
}
}
通过反向查询可以实现相同的结果:
{
post(where: {id: "1"}) {
author {
name
}
}
}
关系过滤器与普通过滤器具有相同的功能,可以使用树修改器之一:
{
every: users(where:{posts_every:{id: "1"}}){name}
none: users(where:{posts_none:{id: "1"}}){name}
some: users(where:{posts_some:{id: "1"}}){name}
}
> WIP. see https://github.com/graphcool/prisma/issues/1312
OpenCRUD暴露以下mutations以进行简单的数据操作
创建单个数据racord:
mutation {
createUser(data: { name: "Karl" }) {
id
}
}
mutation {
updateUser(where: { id: "1" }, data: { name: "Karl" }) {
id
}
}
mutation {
deleteUser(where: { id: "1" }) {
id
}
}
OpenCRUD暴露了如下mutations以操纵一批数据记录。count字段返回受影响的记录数
mutation {
updateManyUsers(where: {name_not: "Karl"}, data:{name: "Karl"}) {
count
}
}
mutation {
deleteManyUsers(where: {name_not: "Karl"}) {
count
}
}
OpenCRUD嵌套mutations是一种操纵关系数据的强大方法。
> WIP. See https://github.com/graphcool/prisma/issues/1280