Prisma API:查询(Queries)

本文属使用Prisma构建GraphQL服务系列。

Prisma API提供两种查询:

  • 对象查询:获取某个对象类型的单个或多个节点
  • 连接查询:暴露高级功能,如聚合(aggregation)和 Relay compliant connections实现强大的分页模型

在使用Prisma API时,以下功能也是值得留意:

  • 分层查询:跨关系提取数据
  • 查询参数:允许过滤,排序,分页等

通常,Prisma API服务是基于其数据模型生成的。要查看Prisma API中的操作,可以使用GraphQL Playground。

在下文中,我们将看看基于如下数据模型的Prisma服务示例查询:

type Post {
  id: ID! @unique
  title: String!
  published: Boolean!
  author: User!
}

type User {
  id: ID! @unique
  age: Int
  email: String! @unique
  name: String!
  accessRole: AccessRole
  posts: [Post!]!
}

enum AccessRole {
  USER
  ADMIN
}

对象查询

我们可以使用对象查询来获取单个节点或某个对象类型的节点列表。

在这里,我们使用posts查询来获取Post节点的列表。在响应中,只包含每个Post节点的idtitle

query {
  posts {
    id
    title
  }
}

我们还可以使用post查询来查询特定的Post节点。请注意,我们使用where参数来选择节点:

query {
  post(where: {
    id: "cixnen24p33lo0143bexvr52n"
  }) {
    id
    title
    published
  }
}

由于User是我们数据模型中的另一种类型,因此users是另一种可用查询。再次,我们可以使用where参数为返回的User指定条件。在这个例子中,我们筛选所有age大于18岁的User节点:

query {
  users(where: {
    age_gt: 18
  }) {
    id
    name
  }
}

这也适用于所有关系,在这里我们提取那些age大于18岁的authorPost节点:

query {
  posts(where: {
    author: {
      age_gt: 18
    }
  }) {
    id
    title
    author {
      name
      age
    }
  }
}

连接查询(Connection queries)

对象查询直接返回节点列表。在特殊情况下或使用高级功能时,使用连接查询是首选选项。它们是中继连接(Relay connections)的延伸(并且完全符合)。中继连接的核心思想是提供关于数据图中边缘的元信息。例如,每条边不仅可以访问关于相应对象(节点)的信息,还可以与允许实现强大分页的游标相关联。

在这里,我们使用postsConnection查询获取所有Post节点。注意我们也要求每个边的cursor

# Fetch all posts
query {
  postsConnection {
    edges {
      cursor
      node {
        id
        title
      }
    }
  }
}

连接查询还通过aggregate显示聚合功能:

# Count all posts with a title containing 'GraphQL'
query {
  postsConnection(where: {
    title_contains: "GraphQL"
  }) {
    aggregate {
      count
    }
  }
}

跨关系查询数据

数据模型中的每个可用关系都会为它所连接的两个模型的查询添加一个新字段。

在这里,我们正在使用posts字段获取特定的User以及所有相关的Post节点:

query {
  user(where: {
    id: "cixnekqnu2ify0134ekw4pox8"
  }) {
    id
    name
    posts {
      id
      published
    }
  }
}

嵌套的user.posts的行为与顶级posts查询完全相同,因为它允许您指定您感兴趣的Post类型的哪些字段。

查询参数

在整个Prisma API中,您会发现可以提供的查询参数以进一步控制查询响应。查询参数有:

  • 使用orderBy按节点任何字段值排序
  • 通过使用where的标量或关系过滤器在查询中选择节点
  • 查询字符串中使用firstbeforelastafterskip对节点分页

排序

查询某个类型的所有节点时,可以为每个类型的标量字段提供orderBy参数:orderBy: _ASCorderBy: _DESC

按照title升序排序:

query {
  posts(orderBy: title_ASC) {
    id
    title
    published
  }
}

published降序排序:

query {
  posts(orderBy: published_DESC) {
    id
    title
    published
  }
}

注意:您所排序的字段不必在实际查询中选择。如果您没有指定顺序,则响应会自动按id字段升序排列。

当前版本不支持按多个字段或关联字段排序

过滤

查询某个类型的所有节点时,可以根据需要为where参数提供不同的参数以约束返回的数据。可用选项取决于所讨论类型上定义的标量和关系字段。

单个过滤

如果您只向where参数提供一个参数,则查询响应将只包含遵守此约束的节点。多个过滤器可以使用ANDOR进行组合,详见下文。

1. 按值过滤

过滤查询响应的最简单方法是提供一个字段值进行过滤。

查询尚未发布(publishedfalse)的所有Post节点:

query {
  posts(where: {
    published: false
  }) {
    id
    title
    published
  }
}

2. 高级过滤

根据您要过滤的字段的类型,您可以使用不同的高级标准来筛选查询响应。

查询title在给定字符串列表中的所有Post节点:

query {
  posts(where: {
    title_in: ["My biggest Adventure", "My latest Hobbies"]
  }) {
    id
    title
    published
  }
}

注意:您必须提供一个列表作为 _in参数:title_in: ["My biggest Adventure", "My latest Hobbies"]

关系过滤

对于一对一关系,可以通过将相关参数嵌套在相关节点中来定义条件。

查询其作者角色为USER的所有Post节点:

query {
  posts(where: {
    author: {
      accessRole: USER
    }
  }) {
    title
  }
}

对于多对多关系,可以使用三个附加参数:everysomenone,来定义条件应该匹配everysomenone相关节点。

查询至少有一个Post已发布(publishedtrue)的所有用户节点:

query {
  users(where: {
    posts_some: {
      published: true
    }
  }) {
    id
    posts {
      published
    }
  }
}

关系过滤器也可用于一对一或多对多关系的嵌套参数。

查询不喜欢ADMIN角色作者的帖子的所有用户节点:

query {
  users(where: {
    likedPosts_none: {
      author: {
        accessRole: ADMIN
      }
    }
  }) {
    name
  }
}

注意:likePosts不是上述数据模型的一部分,但可以通过将相应的字段添加到User类型中:likedPosts: [Post!]! @relation(name: "LikedPosts")。请注意,为避免歧义,我们还为关系提供了一个名称。

组合过滤

您可以使用过滤器组合器ORANDNOT 创建过滤器条件的任意逻辑组合。

使用ORANDNOT

查询发布的所有Post节点,其title包含在给定的字符串列表中:

query {
  posts(where: {
    AND: [{
      title_in: ["My biggest Adventure", "My latest Hobbies"]
    }, {
      published: true
    }]
  }) {
    id
    title
    published
  }
}

注意:ORANDNOT并接受一个列表作为输入,其中每个列表项都是一个对象,因此需要用{}进行包装,例如:AND: [{title_in: ["My biggest Adventure", "My latest Hobbies"]}, {published: true}]

带有ANDORNOT的过滤的任意组合

您可以组合甚至嵌套过滤器组合器ANDORNOT来创建过滤条件的任意逻辑组合。

查询所有已发布并且其title在给定字符串列表中的Post节点,或者查询我们提供的特定id

query($published: Boolean) {
  posts(where: {
    OR: [{
      AND: [{
        title_in: ["My biggest Adventure", "My latest Hobbies"]
      }, {
        published: $published
      }]
    }, {
      id: "cixnen24p33lo0143bexvr52n"
    }]
  }) {
    id
    title
    published
  }
}

请注意,我们是如何将AND组合器嵌套在OR组合器中的,与id值过滤器处于同一级别。

除了过滤器组合器ANDORNOT之外,用于查询类型的所有节点的可用过滤器参数取决于类型的字段及其类型。

目前,既没有标量列表过滤器( scalar list filters)也没有JSON过滤器(JSON filters)可用。在GITHUB的各个特征请求中加入讨论。

分页

查询特定对象类型的所有节点时,可以提供允许您对查询响应进行分页的参数。

分页允许您同时请求一定数量的节点。您可以通过节点向前或向后寻找并提供可选的起始节点:

  • 向前,使用first;使用指定起始节点的after
  • 向后,使用last,使用指定起始节点的before

通过提供skip参数,您还可以跳过任意数量的节点,无论您正在寻找哪个方向。

考虑一个博客,其中只有3个Post节点显示在首页。要查询第一页:

query {
  posts(first: 3) {
    id
    title
  }
}

在第一个Post节点之后查询前两个Post节点:

query {
  posts(
    first: 2
    after: "cixnen24p33lo0143bexvr52n"
  ) {
    id
    title
  }
}

我们可以通过结合firstskip来达到相同的结果:

query {
  posts(
    first: 2
    skip: 1
  ) {
    id
    title
  }
}

查询最后2个Post

query {
  posts(last: 2) {
    id
    title
  }
}

注意:您不能firstbeforelastafter混合,您还可以查询更多的节点,而不会出现错误消息。

请注意,共享演示群集上的每个分页字段最多可以返回1000个节点。使用群集配置(the cluster configuration)的其他群集可以提高此限制。

你可能感兴趣的:(Prisma API:查询(Queries))