Prisma API:订阅(Subscriptions)

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

概述

GraphQL订阅允许您在数据发生更改时实时得到通知。有三种触发订阅的事件:

  • 一个新的节点被创建
  • 现有节点已更新
  • 现有的节点被删除

这是一个订阅示例,每当创建新的Post节点时都会通知您。订阅触发时,服务器发送的有效payload将包含PostdescriptionimageUrl

subscription newPosts {
  post(where: {
    mutation_in: [CREATED]
  }) {
    mutation
    node {
      description
      imageUrl
    }
  }
}

订阅使用特殊的websocket端点。

以下是可用订阅的列表。要探索它们,请在您的服务中使用GraphQL Playground。

  • 对于数据模型中的每种对象类型,都可以使用类型订阅来侦听该类型的数据更改。
  • 目前,连接或断开节点间的关系不会触发订阅!

可以在单个订阅请求中合并多个订阅触发器,以准确控制要通知的事件。订阅API还使用可用于查询的丰富过滤器系统。

请求订阅

使用Apollo Client时,您可以使用apollo-link-ws库来方便订阅。这是一个例子。
您还可以使用GraphQL Playground或任何WebSocket客户端,如下所述。

GraphQL Playground

GraphQL Playground可用来查看和运行GraphQL 订阅

普通WebSockets

1.建立连接

订阅通过WebSockets进行管理。首先建立一个WebSocket连接并指定graphql-subscriptions协议:

let webSocket = new WebSocket('wss://__CLUSTER__.prisma.sh/__WORKSPACE__/__SERVICE__/__STAGE__', 'graphql-subscriptions');

2.发起握手

接下来,您需要启动WebSocket服务器的握手。您可以通过监听open事件然后发送JSON消息到type属性设置为init的服务来执行此操作:

webSocket.onopen = (event) => {
  const message = {
      type: 'init'
  }

  webSocket.send(JSON.stringify(message))
}

3.接收消息

服务可以用各种类型属性来区分各种消息。您可以根据您的应用程序对每条消息作出反应:

webSocket.onmessage = (event) => {
  const data = JSON.parse(event.data)

  switch (data.type) {
    case 'init_success': {
      console.log('init_success, the handshake is complete')
      break
    }
    case 'init_fail': {
      throw {
        message: 'init_fail returned from WebSocket server',
        data
      }
    }
    case 'subscription_data': {
      console.log('subscription data has been received', data)
      break
    }
    case 'subscription_success': {
      console.log('subscription_success')
      break
    }
    case 'subscription_fail': {
      throw {
        message: 'subscription_fail returned from WebSocket server',
        data
      }
    }
  }
}

4.订阅数据更改

要订阅数据更改,请发送type属性设置为subscription_start的消息:

const message = {
  id: '1',
  type: 'subscription_start',
  query: `
    subscription newPosts {
      post(filter: {
        mutation_in: [CREATED]
      }) {
        mutation
        node {
          description
          imageUrl
        }
      }
    }
  `
}

webSocket.send(JSON.stringify(message))

您应该收到type设置为subscription_success的消息。发生数据更改时,您将收到type设置为subscription_data的消息。您在subscription_start消息中提供的id属性将显示在所有subscription_data消息中,允许您复用WebSocket连接。

5.取消订阅

要取消订阅数据更改,请发送type属性设置为subscription_end的消息:

const message = {
  id: '1',
  type: 'subscription_end'
}

webSocket.send(JSON.stringify(message))

类型订阅(Type subscriptions)

对于数据模型中的每种可用对象类型,都会自动生成某些订阅。 作为一个例子,考虑使用单个Post类型的以下数据模型:

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

在生成的Prisma API中,可以使用post订阅,只要某些Post类型的节点被创建,更新或删除,就可以通知post订阅。

创建节点的订阅(Subscribing to created nodes)

对于给定类型,您可以订阅正在使用生成的类型订阅创建的所有节点。

订阅所有创建的节点

如果要订阅Post类型的节点创建,可以使用post订阅并指定where对象并设置mutation_in : [CREATED]

subscription {
  post(where: {
    mutation_in: [CREATED]
  }) {
    mutation
    node {
      description
      imageUrl
      author {
        id
      }
    }
  }
}

有效载(payload)荷包含:

  • mutation: 此时,它将返回CREATED
  • node: 允许您在创建的节点(以及可能的相关节点)上查询信息。

订阅特定的创建节点

对于查询使用的where对象参数,可以使用类似的查询(Queries)中的过滤机制。
例如,用户关注个别author,只通知关注者,推主创建了帖子:

subscription {
  post(where: {
    AND: [{
      mutation_in: [CREATED]
    }, {
    node: {
      author: {
        followedBy_some: {
          id: "cj03x3nacox6m0119755kmcm3"
        }
      }
    }]
  }) {
    mutation
    node {
      description
      imageUrl
      author {
        id
      }
    }
  }
}

订阅已删除的节点

订阅所有已删除的节点

如果要订阅Post类型的更新节点,可以使用post订阅并指定where对象并设置mutation_in: [DELETED]

subscription deletePost {
  post(where: {
    mutation_in: [DELETED]
  }) {
    mutation
    previousValues {
      id
    }
  }
}

有效载荷(payload)包含:

  • mutation: 返回DELETED
  • previousValues: 以前的节点标量值。

注意:previousValuesCREATED订阅中始终返回null

订阅特定的已删除节点

CREATED订阅类似,对于查询使用的where对象参数,可以使用类似的查询(Queries)中的过滤机制。

例如,如果特定用户关注作者,只能通知已删除的帖子:

subscription {
  post(where: {
    mutation_in: [DELETED]
    node: {
      author: {
        followedBy_some: {
          id: "cj03x3nacox6m0119755kmcm3"
        }
      }
    }
  }) {
    mutation
    previousValues {
      id
    }
  }
}

订阅更新的节点(Subscribing to updated nodes)

对于给定的类型,您可以使用生成的类型订阅订阅正在更新的所有节点。

订阅所有更新的节点

如果您想订阅Post类型的更新节点,则可以使用post订阅并指定where对象并设置mutation_in : [UPDATED]

subscription {
  post(where: {
    mutation_in: [UPDATED]
  }) {
    mutation
    node {
      description
      imageUrl
      author {
        id
      }
    }
    updatedFields
    previousValues {
      description
      imageUrl
    }
  }
}

有效载荷(payload)包含:

  • mutation:在这种情况下,它将返回UPDATED。
  • node:允许您查询更新节点和连接节点上的信息。
  • updatedFields:已更改的字段列表。
  • previousValues:节点的以前标量值。

注意:updatedFields对于CREATEDDELETED订阅始终为null。对于CREATED订阅,previousValues始终为null

订阅更新的字段

例如,如果Post中的description字段发生更改,则只能通知订阅:

subscription {
  post(where: {
    mutation_in: [UPDATED]
    updatedFields_contains: "description"
  }) {
    mutation
    node {
      description
    }
    updatedFields
    previousValues {
      description
    }
  }
}

updatedFields_contains类似,存在更多的过滤条件:

  • updatedFields_contains_every: [String!]: 如果指定的所有字段都已更新,则匹配。
  • updatedFields_contains_some: [String!]: 如果某些指定的字段已更新,则匹配。

注意:您不能将updatedFields过滤器条件与mutation_in: [CREATED]或者mutation_in: [DELETED]一起使用!

关系订阅(Relation subscriptions)

目前,关系更新订阅仅在使用UPDATED订阅的解决方法中可用。

订阅关系变更(Subscribing to relation changes)

您可以通过touching节点来强制进行通知更改。将dummy: String字段添加到正在讨论的类型中,并更新此字段以查找关系状态刚更改的节点。

mutation updatePost {
  updatePost(
    where: {
      id: "some-id"
    }
    data: {
      dummy: "dummy" # do a dummy change to trigger update subscription
    }
  )
}

合并订阅(Combining subscriptions)

您可以在一个订阅中订阅同一类型的多个突变。

订阅所有节点的更改(Subscribe to all changes to all nodes)

使用where对象的mutation_in参数,可以选择要订阅的突变类型。例如,要订阅createPostupdatePostdeletePost突变:

subscription {
  post(where: {
    mutation_in: [CREATED, UPDATED, DELETED]
  }) {
    mutation
    node {
      id
      description
    }
    updatedFields
    previousValues {
      description
      imageUrl
    }
  }
}

订阅对特定节点的所有更改(Subscribe to all changes to specific nodes)

要选择要通知的特定节点,请使用where对象的节点参数。你可以把它和mutation_in结合起来。例如,如果特定用户关注作者,只能通知创建,更新和删除的帖子:

subscription {
  post(
    where: {
      mutation_in: [CREATED, UPDATED, DELETED]
    }
    node: {
      author: {
        followedBy_some: {
          id: "cj03x3nacox6m0119755kmcm3"
        }
      }
    }
  ) {
    mutation
    node {
      id
      description
    }
    updatedFields
    previousValues {
      description
      imageUrl
    }
  }
}

高级订阅过滤器(Advanced subscription filters)

示例,您可以订阅所有CREATEDDELETE订阅,以及更新imageUrl时的所有UPDATED订阅:

subscription {
  post(where: {
    OR: [{
      mutation_in: [CREATED, DELETED]
    }, {
      mutation_in: [UPDATED]
      updatedFields_contains: "imageUrl"
    }]
  }) {
    mutation
    node {
      id
      description
    }
    updatedFields
    previousValues {
      description
      imageUrl
    }
  }
}

注意:将任何updatedFields过滤条件与CREATEDDELETED订阅一起使用会导致错误。对于CREATED预订,previousValues始终为null,对于CREATEDDELETED预订,updatedFields始终为null

你可能感兴趣的:(Prisma API:订阅(Subscriptions))