使用Prisma + MongoDB + GraphQL

时间:2019-11-11 14:20:14

标签: node.js mongodb graphql prisma prisma-graphql

我开始将Prisma与mongoDB结合使用,在我看来,最重的方法之一是类别和子类别之间的关系,因为尽管使用@relation,但在子类别中未引用类别(链接:INLINE )。无论如何:我正在使用包含Pet数组的User集合。

我试图在本地服务器(localhost:8000 / graphql)上的Pet文档中获取用户,但是我不能,它显示为NULL。据我所知:理论上,用户不存储在Pet文档(mongoDB)的一侧;因此Prisma会在每个User文档中进行一次昂贵的搜索,将其与Pets数组的每个对象进行比较,但是尽管如此,它还是行不通的。

在Docker上运行的Prisma服务器映像(localhost:4466)可能使我感到困惑。 (获取用户并将其显示给我),而在我的本地服务器(localhost:8000 / graphql)上却没有。

本地服务器(localhost:8000 / graphql):
localhost:8000/graphql
DOCKER上的PRISMA服务器(localhost:4466):
localhost:4466
模式在datamodel.prisma中的外观如下:

type User {
    id: ID! @id
    name: String!
    email: String! @unique
    password: String!
    pets: [Pet!]! @relation(link: INLINE)
    createdAt: DateTime! @createdAt
    updatedAt: DateTime! @updatedAt
}
type Pet {
    id: ID! @id
    name: String!
    description: String!
    sex: String!
    owner: User
    createdAt: DateTime! @createdAt
    updatedAt: DateTime! @updatedAt
}


typeDefs:

type Query {
   feed(where: PetWhereInput, skip: Int, first: Int, orderBy: PetOrderByInput): [Pet]!
}
type Mutation {
    postPet(data: PetCreateInput!): Pet   
}

解析器:

async function feed(parent, args, context, info) {
   return await context.prisma.pets({
      ...args
   })
}

async function postPet(parent, args, context, info) {
   const userId = getUserId(context) //Validate User
      return await context.prisma.createPet({
         ...args.data,
         owner: { connect: { id: userId }} //Create the relationship between User and Pet
      })
   }

这是数据库中的一个示例:
enter image description here
我也尝试过在Pet模式中将User作为非NULL包括在内,但是在进行查询时,出现错误“无法为非null字段Pet.owner返回null。”,因为User(所有者)未在mongoDB中声明

Pet {
   ... //the others are not shown for practical purposes
   owner: User!
}

如果您可以帮助我解决这个大问题,将对您有所帮助。谢谢!!

Pd:有谁知道为什么Prism不允许保存两个引用? UserCollection和PetsCollection

1 个答案:

答案 0 :(得分:0)

显然我犯了一个大错误!我错过了在解析器中实现这两个功能的方法:

function pets(parent, args, context) {
   return context.prisma.user({ id: parent.id }).pets()
}

function owner(parent, args, context) {
   return context.prisma.pet({ id: parent.id }).owner() 
}

我们的GraphQL方案的这两个字段不能以相同的方式解决:Pet中的“所有者”和User中的“ pets”。必须明确实现这些字段,因为我们的GraphQL服务器无法推断从何处获取该数据。

在所有者函数(解析器)中,首先是使用prisma客户端实例获取链接,然后在其上调用“所有者”。注意,解析器需要称为“所有者”,因为它从schema.graphql中的Pet类型解析“所有者”字段。我们可以通过类似的方式解决宠物的关系。

  

资料来源:
  https://github.com/prisma/prisma/issues/4143#issuecomment-474880883   https://www.howtographql.com/graphql-js/6-authentication/