获取一个嵌套的电子邮件字段,该字段是prisma中另一个模型的一部分



我的模式看起来像:

schema.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文件看起来像:

db.ts

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给出了这个打字脚本错误:

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)

我的模式文件看起来像:

schema.ts

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字段时就开始抛出错误,但格式是平面文件,所以我的输出看起来像:

{
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元素。

从本质上讲,你想要的是过滤那些与电子邮件有关联用户的许可证,然后对其进行映射

实际上,你可以用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链接。请注意,esint正在抱怨(期望在箭头函数的末尾返回一个值(。https://codesandbox.io/s/nifty-surf-s8vcg6?file=/src/index.ts

我禁用了db.ts文件上的TS&然后检查CCD_ 11阵列&发现我需要将email作为null而不是undefined

一个重要的注意事项是:在License类型的nexus配置中,我不得不停止对email使用nonNull来停止错误。

工作解决方案已发布在此提交中。它现在工作:(

最新更新