跳到主要內容

result:為查詢結果新增自定義欄位和方法

資訊

Prisma Client 擴充套件在 4.16.0 及更高版本中已正式釋出。它們在 4.7.0 版本中作為預覽功能引入。如果您執行的版本低於 4.16.0,請確保啟用 clientExtensions 預覽功能標誌。

您可以使用 result Prisma Client 擴充套件元件型別,為查詢結果新增自定義欄位和方法。

使用 $extends 客戶端級別方法來建立一個 *擴充套件客戶端*。擴充套件客戶端是標準 Prisma Client 的一個變體,它被一個或多個擴充套件所包裝。

要為查詢結果新增自定義欄位方法,請使用以下結構。在此示例中,我們向 user 模型查詢的結果新增自定義欄位 myComputedField

const prisma = new PrismaClient().$extends({
name?: 'name',
result?: {
user: { // in this case, we extend the `user` model
myComputedField: { // the name of the new computed field
needs: { ... },
compute() { ... }
},
},
},
});

引數如下

  • name:(可選)為擴充套件指定一個名稱,該名稱將顯示在錯誤日誌中。
  • result:定義查詢結果的新欄位和方法。
  • needs:一個物件,描述結果欄位的依賴項。
  • compute:一個方法,定義虛擬欄位在訪問時如何計算。

為查詢結果新增自定義欄位

您可以使用 result 擴充套件元件為查詢結果新增欄位。這些欄位在執行時計算,並且是型別安全的。

在以下示例中,我們為 user 模型添加了一個名為 fullName 的新虛擬欄位。

const prisma = new PrismaClient().$extends({
result: {
user: {
fullName: {
// the dependencies
needs: { firstName: true, lastName: true },
compute(user) {
// the computation logic
return `${user.firstName} ${user.lastName}`
},
},
},
},
})

const user = await prisma.user.findFirst()

// return the user's full name, such as "John Doe"
console.log(user.fullName)

在上述示例中,compute 的輸入 user 會根據 needs 中定義的物件自動推斷型別。firstNamelastName 的型別為 string,因為它們在 needs 中指定。如果它們未在 needs 中指定,則無法訪問它們。

在另一個計算欄位中重用計算欄位

以下示例以型別安全的方式計算使用者的稱謂和全名。titleFullName 是一個計算欄位,它重用了 fullName 計算欄位。

const prisma = new PrismaClient()
.$extends({
result: {
user: {
fullName: {
needs: { firstName: true, lastName: true },
compute(user) {
return `${user.firstName} ${user.lastName}`
},
},
},
},
})
.$extends({
result: {
user: {
titleFullName: {
needs: { title: true, fullName: true },
compute(user) {
return `${user.title} (${user.fullName})`
},
},
},
},
})

欄位注意事項

  • 出於效能原因,Prisma Client 在訪問時計算結果,而不是在檢索時計算。

  • 您只能建立基於標量欄位的計算欄位。

  • 您只能將計算欄位與 select 結合使用,並且不能對其進行聚合。例如

    const user = await prisma.user.findFirst({
    select: { email: true },
    })
    console.log(user.fullName) // undefined

為結果物件新增自定義方法

您可以使用 result 元件為查詢結果新增方法。以下示例為結果物件添加了一個新方法 save

const prisma = new PrismaClient().$extends({
result: {
user: {
save: {
needs: { id: true },
compute(user) {
return () =>
prisma.user.update({ where: { id: user.id }, data: user })
},
},
},
},
})

const user = await prisma.user.findUniqueOrThrow({ where: { id: someId } })
user.email = 'mynewmail@mailservice.com'
await user.save()

omit 查詢選項與 result 擴充套件元件結合使用

您可以將 omit(預覽)選項自定義欄位以及自定義欄位所需的欄位結合使用。

從查詢結果中 omit 自定義欄位所需的欄位

如果您 omit 一個作為自定義欄位依賴項的欄位,即使它不包含在查詢結果中,它仍將從資料庫中讀取。

以下示例 omitpassword 欄位,它是自定義欄位 sanitizedPassword 的一個依賴項

const xprisma = prisma.$extends({
result: {
user: {
sanitizedPassword: {
needs: { password: true },
compute(user) {
return sanitize(user.password)
},
},
},
},
})

const user = await xprisma.user.findFirstOrThrow({
omit: {
password: true,
},
})

在這種情況下,儘管 password 從結果中被 omit 掉,但它仍然會從資料庫中查詢,因為它屬於 sanitizedPassword 自定義欄位的依賴項。

從查詢結果中 omit 自定義欄位及其依賴項

為確保省略的欄位完全不從資料庫中查詢,您必須同時 omit 自定義欄位及其依賴項。

以下示例同時 omit 了自定義欄位 sanitizedPassword 和依賴欄位 password

const xprisma = prisma.$extends({
result: {
user: {
sanitizedPassword: {
needs: { password: true },
compute(user) {
return sanitize(user.password)
},
},
},
},
})

const user = await xprisma.user.findFirstOrThrow({
omit: {
sanitizedPassword: true,
password: true,
},
})

在這種情況下,同時 omit passwordsanitizedPassword 將導致兩者都從結果中排除,並阻止 password 欄位從資料庫中讀取。

限制

目前,Prisma Client 的結果擴充套件元件不支援關係欄位。這意味著您無法基於關係型關聯中的相關模型或欄位(例如 user.posts、post.author)建立自定義欄位或方法。needs 引數只能引用同一模型中的標量欄位。請關注 GitHub 上的 #20091 問題

const prisma = new PrismaClient().$extends({
result: {
user: {
postsCount: {
needs: { posts: true }, // This will not work because posts is a relation field
compute(user) {
return user.posts.length; // Accessing a relation is not allowed
},
},
},
},
})
© . This site is unofficial and not affiliated with Prisma Data, Inc.