Какой должна быть схема отношений между микросервисами
Я использую NestJS + Prisma + Apollo Federation.
В микросервисе A есть определение пользователя, в микросервисе B - сообщения. Отношение 1 - N, у пользователя может быть N сообщений.
В Prisma модель данных Post определяется строкой для пользователя, поскольку userId - это uuid.
type Post {
id: Int! @id
createdAt: DateTime! @createdAt
updatedAt: DateTime! @updatedAt
user: String!
}
В сгенерированной схеме (с https://graphql-code-generator.com/) Post имеет атрибут типа User, и этот тип User расширяет идентификатор и массив сообщений:
type Post @key(fields: "id") {
id: Int!
createdAt: DateTime!
updatedAt: DateTime!
user: User!
}
extend type User @key(fields: "id") {
id: ID! @external
posts: [Post]
}
В федерации apollo все работает, как ожидалось, за исключением случаев, когда делается запрос на установление связи между обоими микросервисами.
На игровой площадке, если вы попытаетесь запросить сообщения с его пользователем без установки подполей, это нарушит схему и скажет, что вы должны установить подполя пользователя, и если вы установите подполя, graphql ответит сообщением, что вы не можете использовать подполя, потому что его тип это строка.
Единственный способ, которым я мог сделать это правильно, - это установить в Prisma поле userId типа string и установить другое поле в схеме с именем user типа User. Но во всех примерах не было поля для работы с db и поля для работы со схемой.
Мой вопрос: рекомендуется ли это или я что-то упускаю.
1 ответ
Чтобы получить 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
}