代码之家  ›  专栏  ›  技术社区  ›  tacos_tacos_tacos

使用Prisma生成的包装器查询节点时包含关系

  •  3
  • tacos_tacos_tacos  · 技术社区  · 6 年前

    我在跟踪 GraphQL Prisma Typescript

    我的数据模型包括以下节点:

    type User {
      id: ID! @unique
      displayName: String!
    }
    
    type SystemUserLogin {
      id: ID! @unique
      username: String! @unique
      passwordEnvironmentVariable: String!
      user: User!
    }
    

    mutation {
      systemUserLogin: createSystemUserLogin({
        data: {
          username: "SYSTEM",
          passwordEnvironmentVariable: "SYSTEM_PASSWORD",
          user: {
            create: {
              displayName: "System User"
            }
          }
        }
      })
    }
    

    我创造了一个突变样本 login

    login: async (_parent, { username, password }, ctx) => {
        let user
        const systemUser = await ctx.db.systemUserLogin({ username })
        const valid = systemUser && systemUser.passwordEnvironmentVariable && process.env[systemUser.passwordEnvironmentVariable] &&(process.env[systemUser.passwordEnvironmentVariable] === password)
    
        if (valid) {
          user = systemUser.user // this is always undefined!
        }
    
        if (!valid || !user) {
          throw new Error('Invalid Credentials')
        }
    
        const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET)
    
        return {
          token,
          user: ctx.db.user({ id: user.id }),
        }
      },
    

    但不管我做什么, systemUser.user

    这是有意义的-客户机包装器如何知道在没有我告诉它的情况下递归到图中的“深度”?

    但是我怎么能告诉它我想包括 User 关系?

    prisma-client

    export const SystemUserLogin: SystemUserLoginResolvers.Type<TypeMap> = {
      id: parent => parent.id,
      user: (parent, args, ctx: any) => {
        console.log('resolving')
        return ctx.db.systemUserLogin({id: parent.id}).user()
      },
      environmentVariable: parent => parent.environmentVariable,
      systemUsername: parent => parent.systemUsername,
      createdAt: parent => parent.createdAt,
      updatedAt: parent => parent.updatedAt
    };
    

    还有。。。

      let identity: UserParent;
    
      const systemUserLogins = await context.db.systemUserLogins({
        where: {
          systemUsername: user,
        }
      });
      const systemUserLogin = (systemUserLogins) ? systemUserLogins[0] : null ;
    
      if (systemUserLogin && systemUserLogin.environmentVariable && process.env[systemUserLogin.environmentVariable] && process.env[systemUserLogin.environmentVariable] === password) {
        console.log('should login!')
    
        identity = systemUserLogin.user; // still null
      }
    

    编辑2:这里是存储库

    https://github.com/jshin47/annotorious/tree/master/server

    2 回复  |  直到 6 年前
        1
  •  4
  •   nburk    6 年前

    目前有两种方法可以解决这个问题:

    • 使用 就像OP现在所做的那样
    • 使用 Prisma绑定

    您可以在中进一步了解Prisma客户端和Prisma绑定之间的区别 this 论坛帖子。

    由于OP目前正在使用Prisma客户端,因此我也将使用它来回答这个问题!

    这是有意义的-客户机包装器如何知道在没有我告诉它的情况下递归到图中的“深度”?

    明确地 $fragment API Prisma docs :

    每当使用Prisma客户机查询模型时,都会获取该模型的所有标量字段。无论查询单个对象还是对象列表,都是如此。

    那么,如何妥善解决这种情况呢?事实上,解决办法是 改变Prisma客户机的使用方式,但是实现一个额外的GraphQL解析器函数!

    解析程序的要点是,它们正在为 具体的 架构中的字段。在OP的例子中,目前没有解析程序可以“解析” user SystemUserLogin 类型:

    type SystemUserLogin {
      id: ID! @unique
      username: String! @unique
      passwordEnvironmentVariable: String!
      user: User! # GraphQL doesn't know how to resolve this
    }
    

    要解决这种情况,您需要为其实现一个专用的“类型解析器”,如下所示:

    const resolvers = {
      SystemUserLogin: {
        user(parent, args, ctx) {
          return ctx.db.systemUserLogin({id: parent.id}).user()
        }
      } 
    }
    

    完全披露:我在Prisma工作,我们正在为这个用例添加更好的文档和资源。还可以结账 this author posts 出于同样的原因,关系字段是必需的。

    编辑 Common resolver patterns .

        2
  •  1
  •   Raeesaa    6 年前

    prisma绑定函数的第二个参数接受GraphQL查询字符串。更改以下行

    const systemUser = await ctx.db.query.systemUserLogin({ username })
    

    const systemUser = await ctx.db.query.systemUserLogin({ username }, `{id username user {id displayName}}`)
    

    会给你用户的数据。