[英]get a nested email field that is part of another model in prisma?
我的架构看起来像:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
model User {
id String @id @default(cuid())
email String? @unique
stripeId String @unique
createdAt DateTime @default(now())
product Product?
@@map("users")
}
model Product {
id String @id @default(cuid())
totalSum Int @default(9700)
user User @relation(fields: [userId], references: [id])
userId String @unique
licenses License[]
@@map("products")
}
model License {
id String @id @default(cuid())
name String @unique
/// no. of licenses generated
total Int @default(1)
/// no. of licenses used
used Int @default(0)
/// stored in cents
product Product? @relation(fields: [productId], references: [id])
productId String?
createdAt DateTime @default(now())
@@map("licenses")
}
我想在执行prisma.license.findMany()
时访问email
字段。 我的db
文件看起来像:
import { Prisma, License, User } from '@prisma/client'
import { prisma } from './context'
export const getLicenses = async (): Promise<
Array<License & Pick<User, 'email'>> | null | undefined
> => {
const userSelect = Prisma.validator<Prisma.ProductSelect>()({
user: {
select: {
email: true,
},
},
})
const productSelect = Prisma.validator<Prisma.LicenseSelect>()({
product: {
include: userSelect,
},
})
const licenses = await prisma.license.findMany({
orderBy: {
createdAt: 'desc',
},
include: productSelect,
})
const result = licenses.map((license) => {
const email = license.product?.user.email
if (email) {
return {
...license,
email,
}
}
})
return result
}
export const db = {
getLicenses,
}
最后一行return result
给出了这个 typescript 错误:
Type '({ email: string; id: string; name: string; total: number; used: number; productId: string | null; createdAt: Date; product: (Product & { user: { email: string | null; }; }) | null; } | undefined)[]' is not assignable to type '(License & Pick<User, "email">)[]'.
Type '{ email: string; id: string; name: string; total: number; used: number; productId: string | null; createdAt: Date; product: (Product & { user: { email: string | null; }; }) | null; } | undefined' is not assignable to type 'License & Pick<User, "email">'.
Type 'undefined' is not assignable to type 'License & Pick<User, "email">'.
Type 'undefined' is not assignable to type 'License'.ts(2322)
我的架构文件如下所示:
import { db } from './db'
const Query = objectType({
name: 'Query',
definition(t) {
t.list.field('licenses', {
type: 'License',
resolve: async (_, __, ctx) => {
if (!ctx.admin.isLoggedIn) return null
const licenses = await db.getLicenses()
if (licenses) return licenses
return null
},
})
},
})
即使是这个小查询也给我带来了很多错误。 当我想使用prisma.license.findMany()
查询所有许可证时,它曾经可以工作,但是一旦我想要email
字段但采用平面文件格式,它就开始抛出错误,所以我的 output 看起来像:
{
id: string;
name: string;
total: number;
used: number;
productId: string | null;
createdAt: Date;
email: string;
}
我也不希望发送productId
。 我该如何解决这个问题?
我做了一个最小的复制→ https://github.com/deadcoder0904/prisma-nested-query-email
当您使用 Array.map 时,如果您没有明确指定每个元素的返回值,那么undefined
将进入您的数组 - 这就是您的 TS 错误所指示的内容。 如果 (,email),则 map 将undefined
的元素返回到 output 数组。
本质上,您想要过滤那些与 email 和 THEN map 关联的用户的许可证。
你实际上可以用 reduce 来做到这一点。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#replace_.filter.map_with_.reduce
您正在尝试使用 Array.map LIKE 这个 Array.reduce 功能(可以替换过滤器/映射)。 但是如果你用 Array.reduce 实现 undefined 就不能潜入返回的数组。
这是一个相关的 CodeSandbox 链接。 请注意, eslint 正在抱怨(预计在箭头函数的末尾返回一个值)。 https://codesandbox.io/s/nifty-surf-s8vcg6?file=/src/index.ts
我在db.ts
文件上禁用了 TS,然后检查了results
数组并发现我需要将email
为null
而不是undefined
。
一个重要的注意事项:我必须停止在License
类型的nexus
配置中对email
使用nonNull
来停止错误。
工作解决方案发布在此提交中。 现在可以了:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.