使用 Prisma 生成的包装器查询节点时包含关系
Include relationship when querying node using Prisma generated wrapper
我按照 Prisma 提供的 GraphQL Prisma Typescript 示例创建了一个简单的数据模型,为 Prisma 客户端和解析器等生成了代码。
我的数据模型包括以下节点:
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
总是未定义的!
这是有道理的 - 客户端包装器如何知道如何 "deep" 在我不告诉它的情况下递归到图中?
但是我如何告诉它我想包含 User
关系?
编辑:我尝试了下面的建议来使用 prisma-client
。
但是 none 我的解析器似乎被调用过...
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:这是存储库
prisma 绑定函数的第二个参数接受 GraphQL 查询字符串。从
更改以下行
const systemUser = await ctx.db.query.systemUserLogin({ username })
至
const systemUser = await ctx.db.query.systemUserLogin({ username }, `{id username user {id displayName}}`)
会给你用户的数据。
Prisma 绑定将 return 只有模型的直接属性,以防第二个参数未传递给它。
目前有两种方法可以解决这个问题:
- 像 OP 目前那样使用 Prisma 客户端
- 使用 Prisma 绑定,正如@User97 在接受的答案中所建议的那样
您可以在 this 论坛 post 中了解有关 Prisma 客户端和 Prisma 绑定之间区别的更多信息。
由于 OP 目前正在使用 Prisma 客户端,我也将使用它来回答这个问题!
让我们看一下OP在问题中的陈述:
This makes sense - how would the client wrapper know how "deep" to recurse into the graph without me telling it?
OP 正确地指出 Prisma 客户端不知道如何深入到图表中以及要获取什么关系。事实上,除非 明确地 另有说明(例如使用 $fragment
API), the client will never fetch any relationships and will always only fetch the scalar values. From the Prisma docs:
Whenever a model is queried using the Prisma client, all scalar fields of that model are fetched. This is true no matter if a single object or a list of objects is queried.
那么,如何正确解决这种情况呢?事实上,解决方案不是改变Prisma客户端的使用方式,而是实现一个额外的GraphQL解析器功能!
关于解析器的要点是它们正在为您的架构中的特定 字段获取数据。在 OP 的情况下,目前没有解析器可以“解析”在 SystemUserLogin
类型上定义的 user
关系:
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
关系字段的显式解析器。
希望对您有所帮助!
编辑:我们还在 Prisma 教程中添加了关于 Common resolver patterns.
的更详尽的解释
我按照 Prisma 提供的 GraphQL Prisma Typescript 示例创建了一个简单的数据模型,为 Prisma 客户端和解析器等生成了代码。
我的数据模型包括以下节点:
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
总是未定义的!
这是有道理的 - 客户端包装器如何知道如何 "deep" 在我不告诉它的情况下递归到图中?
但是我如何告诉它我想包含 User
关系?
编辑:我尝试了下面的建议来使用 prisma-client
。
但是 none 我的解析器似乎被调用过...
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:这是存储库
prisma 绑定函数的第二个参数接受 GraphQL 查询字符串。从
更改以下行const systemUser = await ctx.db.query.systemUserLogin({ username })
至
const systemUser = await ctx.db.query.systemUserLogin({ username }, `{id username user {id displayName}}`)
会给你用户的数据。
Prisma 绑定将 return 只有模型的直接属性,以防第二个参数未传递给它。
目前有两种方法可以解决这个问题:
- 像 OP 目前那样使用 Prisma 客户端
- 使用 Prisma 绑定,正如@User97 在接受的答案中所建议的那样
您可以在 this 论坛 post 中了解有关 Prisma 客户端和 Prisma 绑定之间区别的更多信息。
由于 OP 目前正在使用 Prisma 客户端,我也将使用它来回答这个问题!
让我们看一下OP在问题中的陈述:
This makes sense - how would the client wrapper know how "deep" to recurse into the graph without me telling it?
OP 正确地指出 Prisma 客户端不知道如何深入到图表中以及要获取什么关系。事实上,除非 明确地 另有说明(例如使用 $fragment
API), the client will never fetch any relationships and will always only fetch the scalar values. From the Prisma docs:
Whenever a model is queried using the Prisma client, all scalar fields of that model are fetched. This is true no matter if a single object or a list of objects is queried.
那么,如何正确解决这种情况呢?事实上,解决方案不是改变Prisma客户端的使用方式,而是实现一个额外的GraphQL解析器功能!
关于解析器的要点是它们正在为您的架构中的特定 字段获取数据。在 OP 的情况下,目前没有解析器可以“解析”在 SystemUserLogin
类型上定义的 user
关系:
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
关系字段的显式解析器。
希望对您有所帮助!
编辑:我们还在 Prisma 教程中添加了关于 Common resolver patterns.
的更详尽的解释