简体   繁体   English

得到一个嵌套的 email 字段,它是棱镜中另一个 model 的一部分?

[英]get a nested email field that is part of another model in prisma?

i have schema that looks like:我的架构看起来像:

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")
}

i want to access email field while doing prisma.license.findMany() .我想在执行prisma.license.findMany()时访问email字段。 my db file looks like:我的db文件看起来像:

db.ts数据库.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,
}

the last line return result gives this typescript error:最后一行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)

my schema file looks like:我的架构文件如下所示:

schema.ts架构.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
      },
    })
  },
})

even this little query is causing me a lot of errors.即使是这个小查询也给我带来了很多错误。 it used to work when i wanted to query all of licenses using prisma.license.findMany() but it started throwing errors as soon as i wanted email field but in a flat file format so my output looks like:当我想使用prisma.license.findMany()查询所有许可证时,它曾经可以工作,但是一旦我想要email字段但采用平面文件格式,它就开始抛出错误,所以我的 output 看起来像:

{
    id: string;
    name: string;
    total: number;
    used: number;
    productId: string | null;
    createdAt: Date;
    email: string;
}

i also don't want productId to be sent.我也不希望发送productId how can i solve this?我该如何解决这个问题?

i've made a minimal repro → https://github.com/deadcoder0904/prisma-nested-query-email我做了一个最小的复制→ https://github.com/deadcoder0904/prisma-nested-query-email

When you use Array.map, if you don't explicitly specify the return for every element, then undefined will make its way into your array - which is what your TS error is indicating.当您使用 Array.map 时,如果您没有明确指定每个元素的返回值,那么undefined将进入您的数组 - 这就是您的 TS 错误所指示的内容。 If (,email), then map returns an undefined element to the output array.如果 (,email),则 map 将undefined的元素返回到 output 数组。

Essentially, what you want is to filter those licenses that have an associated user with an email, and THEN map it.本质上,您想要过滤那些与 email 和 THEN map 关联的用户的许可证。

You can actually do this with reduce instead.你实际上可以用 reduce 来做到这一点。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#replace_.filter.map_with_.reduce https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#replace_.filter.map_with_.reduce

You're trying to use Array.map LIKE this Array.reduce functionality (which can replace filter/map).您正在尝试使用 Array.map LIKE 这个 Array.reduce 功能(可以替换过滤器/映射)。 But undefined can't sneak into the returned array if you implement with Array.reduce.但是如果你用 Array.reduce 实现 undefined 就不能潜入返回的数组。

Here's a relevant CodeSandbox link.这是一个相关的 CodeSandbox 链接。 Note that eslint is complaining (expected to return a value at the end of arrow function).请注意, eslint 正在抱怨(预计在箭头函数的末尾返回一个值)。 https://codesandbox.io/s/nifty-surf-s8vcg6?file=/src/index.ts https://codesandbox.io/s/nifty-surf-s8vcg6?file=/src/index.ts

I disabled TS on the db.ts file & then checked results array & figured out I needed to have email as null instead of undefined .我在db.ts文件上禁用了 TS,然后检查了results数组并发现我需要将emailnull而不是undefined

One important note: I had to stop using nonNull for email in nexus configuration of type License to stop the error.一个重要的注意事项:我必须停止在License类型的nexus配置中对email使用nonNull来停止错误。

The working solution is posted in this commit .工作解决方案发布在此提交中。 It works now:)现在可以了:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM