Add custom fields and methods to query results
You can use the result
Prisma Client extensions component type to add custom fields and methods to query results. We introduced this feature in version 4.7.0.
Enable the preview feature
Before you create Prisma Client extensions, you must enable the clientExtensions
feature flag in the generator
block of your schema.prisma
file, as follows:
generator client {provider = "prisma-client-js"previewFeatures = ["clientExtensions"]}
Add custom fields or methods to query results
Use the $extends
client-level method to create an extended client. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions.
Use the result
extension component to add custom fields and methods to query results.
To add a custom field or method to query results, use the following structure. In this example, we add the custom field myComputedField
to the result of a user
model query.
const xprisma = prisma.$extends({name?: 'name',result?: {user: { // in this case, we extend the `user` modelmyComputedField: { // the name of the new computed fieldneeds: { ... },compute() { ... }},},},});
The parameters are as follows:
name
: (optional) specifies a name for the extension that appears in error logs.result
: defines new fields and methods to the query results.needs
: an object which describes the dependencies of the result field.compute
: a method that defines how the virtual field is computed when it is accessed.
Add a custom field to query results
You can use the result
extension component to add fields to query results. These fields are computed at runtime and are type-safe.
In the following example, we add a new virtual field called fullName
to the user
model.
const xprisma = prisma.$extends({result: {user: {fullName: {// the dependenciesneeds: { firstName: true, lastName: true },compute(user) {// the computation logicreturn `${user.firstName} ${user.lastName}`},},},},})const user = await xprisma.user.findFirst()// return the user's full name, such as "John Doe"console.log(user.fullName)
In above example, the input user
of compute
is automatically typed according to the object defined in needs
. firstName
and lastName
are of type string
, because they are specified in needs
. If they are not specified in needs
, then they cannot be accessed.
When you call a method in an extension, use the constant name from your $extends
statement, not prisma
. In the above example, xprisma.user.findFirst
computes the virtual field, but prisma.user.findFirst
would not.
Re-use a computed field in another computed field
The following example computes a user's title and full name in a type-safe way. titleFullName
is a computed field that reuses the fullName
computed field.
const xprisma = prisma.$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})`},},},},})
Considerations for fields
For performance reasons, Prisma Client computes results on access, not on retrieval.
You can only create computed fields that are based on scalar fields.
You can only use computed fields with
select
and you cannot aggregate them. For example:const user = await xprisma.user.findFirst({ select: { email: true }))console.log(user.fullName) // undefined
Add a custom method to the result object
You can use the result
component to add methods to query results. The following example adds a new method, save
to the result object.
const xprisma = prisma.$extends({result: {user: {save: {needs: { id: true },compute(user) {return () =>prisma.user.update({ where: { id: user.id }, data: user })},},},},})const user = await xprisma.user.findUniqueOrThrow({ where: { id: someId } })user.email = 'mynewmail@mailservice.com'await user.save()
When you call a method in an extension, use the constant name from your $extends
statement, not prisma
. In the above example, xprisma.user.findUniqueOrThrow
works, but prisma.user.findUniqueOrThrow
does not.