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: <field>_ASCorderBy: <field>_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
  }
}

注意:您必须提供一个列表作为<field> _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)的其他群集可以提高此限制。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 本文属使用Prisma构建GraphQL服务系列。 概述 Prisma使用GraphQL Schema Defi...
    guog阅读 1,415评论 0 1
  • 去年有段时间得空,就把谷歌GAE的API权威指南看了一遍,收获颇丰,特别是在自己几乎独立开发了公司的云数据中心之后...
    骑单车的勋爵阅读 20,431评论 0 41
  • 如果说我的助推鹏烈是DISC派来的天使,那你们,我亲爱的组员们,你们就是那一双双美丽的翅膀。因为有你们,凡人才能变...
    小白老师_Shirley阅读 605评论 0 2
  • 正直君对阿糖的第一印象,是清脆好听的少女音,带点懒散含柔的小娇气,他无端的想到了自己窗台上种的几株淡紫色的风铃草,...
    沈狸阅读 178评论 0 4