微服务之间的关系架构应该如何

时间:2020-04-27 21:07:59

标签: apollo nestjs apollo-federation nestjs-gateways

我正在使用NestJS + Prisma + Apollo Federation。

在微服务A上定义用户,在微服务B上定义帖子。 关系是1-N,一个用户可以有N个帖子。

在Prisma中,由于userId是一个uuid,因此Post的数据模型是使用用户的String定义的。

type Post {
  id: Int! @id
  createdAt: DateTime! @createdAt
  updatedAt: DateTime! @updatedAt
  user: String!
}

在生成的模式(带有https://graphql-code-generator.com)中,Post具有类型为User的属性,而该类型的User扩展了id和一组帖子:

type Post @key(fields: "id") {
  id: Int!
  createdAt: DateTime!
  updatedAt: DateTime!
  user: User!
}

extend type User @key(fields: "id") {
  id: ID! @external
  posts: [Post]
}

在阿波罗联盟中,所有工作均按预期进行,除非进行查询以尝试在两个微服务之间进行链接。

在操场上,如果尝试在不设置子字段的情况下用其用户查询帖子,则会破坏架构并说您必须设置User的子字段,如果设置了子字段,graphql会显示一条消息,提示您无法使用子字段因为它的类型是String。

我可以正确执行此操作的唯一方法是在Prisma中设置字符串类型的userId字段,并在模式中设置另一个名为User类型的用户的字段。但是所有示例都没有显示使用db的字段和使用架构的字段。

我的问题是建议这样做还是我错过了什么?

1 个答案:

答案 0 :(得分:0)

为了从User获取Post,必须在帖子和用户服务中创建一个解析器。

邮政服务

const resolvers = {
  Post:{//before you do this you have to extend User schema which you already did.
      // you are basically asking the 'User' service, which field should be used to query user.
    user: ref => ({ __typename: 'User', id: ref.userId })
  }
  Query:{
    // query resolvers
  },
  Mutation:{
    // mutation resolvers
  }

用户服务

const resolvers = {
  User:{//the code below allows other services to extend User in their own schemas
    __resolveReference: (ref, { userDataLoader }) => userDataLoader.load(ref.id),
  }
  Query:{
    // query resolvers
  },
  Mutation:{
    // mutation resolvers
  }

现在,像[Post]这样的链接数组必须完全在邮政服务中完成

邮政服务

const resolvers = {
  Post:{//before you do this you have to extend User schema which you already did.
      // you are basically telling the user service, which field should be used to query user.
    user: ref => ({ __typename: 'User', id: ref.user })
  },
  User:{
    posts:(ref, args, {postDataLoader}) => getOrders(ref.postIds) //or ref.userId(foreign key)
  },
  Query:{
    // query resolvers
  },
  Mutation:{
    // mutation resolvers
  }