-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement exists
function
#5022
Comments
I agree! As a current workaround, you may define a utility function /**
* Determines whether something exists.
* @param ts
*/
export function $exists<T>(ts: T[]): boolean {
return ts.length > 0
}
const isHost = ctx.prisma.meal
.findMany({
where: {
id,
host: { id: user.id },
},
})
.then($exists) |
exists
function
This comment has been minimized.
This comment has been minimized.
Is this in the current roadmap? |
You may also perform a count + Boolean cast like const isHost = await prisma.meal
.count({
where: {
id,
host: { id: user.id },
},
})
.then(Boolean) |
for many cases a Compare https://blog.jooq.org/avoid-using-count-in-sql-when-you-could-use-exists/ |
To get some inspiration how other ORMs deal with this:
|
is this one happening? |
Hey @greguintow 👋 I'd also love to see this feature but as of now there doesn't seem to be a timeline for it unfortunately since it's not yet placed on the roadmap. In the meantime, the workaround by @SebastienElet is probably the best way to achieve the same outcome, sorry for the inconvenience here 🙏 |
@nikolasburk i have several api's which checks existence of a value. for example for each product i would like to see if the user has liked that product or not. again there are so many other use cases. thank you for the response. and i hope this feature will be implemented soon. :) |
Avoid using Why would you calculate conditions to count through virtually all records when you only need to stop after first match? Implementation without count is simple, just const isHost = await prisma.meal
.findMany({
where: {
id,
host: { id: user.id },
},
select: { id: true }, // this line might not be necessary
take: 1 // this is the important bit
})
.then(r => r.length > 0) Performance in SQL (postgres and mysql) of Edit: Alternative implementation, simpler in js by my coworker @gabymorgi, findFirst returns null if not found. You can use the value in a condition as a truthy value if record exists, or cast to boolean for safety. const isHost = await prisma.meal
.findFirst({ // using findFirst instead of findMany will not return an array
where: {
id,
host: { id: user.id },
},
select: { id: true }, // this line might not be necessary
})
.then(r => Boolean(r)) // optional line. Can use truthiness of one record directly (findfirst returns null if not found) |
Looks like that's an argument in favor of adding |
I vote with exists, it's easier for newcomers to understand code's readability. |
I'd love this too. Am I correct to think that this existed in a previous version of Prisma? See here: |
@anton-johansson Yes, looks like it. My google search earlier actually landed me in that page making me confused why I can't find |
Landed here with same thought why the exists "existed" on V1 but not current version. |
I got it working with Client Extensions: const prisma_ = new PrismaClient();
export const prisma = prisma_
.$extends({
model: {
user: {
exists(where: Parameters<typeof prisma_.user.findFirst>[0]['where']) {
return prisma.user.findFirst({
where,
select: {
id: true
}
}).then(Boolean);
}
},
// Other models go here
}
}); The biggest downside is that I had to repeat it for every single model. |
This comment was marked as abuse.
This comment was marked as abuse.
3 similar comments
This comment was marked as abuse.
This comment was marked as abuse.
This comment was marked as abuse.
This comment was marked as abuse.
This comment was marked as abuse.
This comment was marked as abuse.
@serg06 const prisma = new PrismaClient().$extends({
model: {
$allModels: {
async exists<T>(this: T, where: Prisma.Args<T, 'findFirst'>['where']): Promise<boolean> {
const context = Prisma.getExtensionContext(this)
const result = await (context as any).findFirst({ where })
return result !== null
},
},
},
}) |
I think this issue can be closed with that last coment |
For now we won't close any of the issues for use cases that are now possible via Client extensions until those have stabilized, and are packaged up and documented. |
Exists implementation has a problem when you use transactions.
It creates a new context vs using the existing one. So you cant select the one that was created above. |
Reproduction: datasource postgres {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
output = "../prisma/generated/client"
previewFeatures = ["clientExtensions"]
}
model Equipment {
id String @id @default(cuid())
name String?
} import { Prisma, PrismaClient } from "./prisma/generated/client";
async function main() {
const rootPrisma = new PrismaClient({
log: [
{
emit: "event",
level: "query",
},
],
}).$extends({
model: {
$allModels: {
async exists<T>(
this: T,
where: Prisma.Args<T, "findFirst">["where"],
): Promise<boolean> {
const context = Prisma.getExtensionContext(this);
const result = await (context as any).findFirst({ where });
console.log("exists", { result });
return result !== null;
},
},
},
});
rootPrisma.$on("query", e => {
console.log("Query: " + e.query);
console.log("Params: " + e.params);
console.log("Duration: " + e.duration + "ms");
});
await rootPrisma.$connect();
rootPrisma.$transaction(async prisma => {
const { id } = await prisma.equipment.create({ data: { name: "test" } });
const findResult = await prisma.equipment.findFirst({ where: { id } });
const existsResult = await prisma.equipment.exists({ id });
console.log("transaction", { findResult, existsResult });
});
}
main().catch(console.error);
|
Is there a way of accessing the model itself without type-casting to |
@janpio this is possible with the client extensions, and those are now "stabilized", but to me it seems like an |
Imo, this is very desirable. Implementations of the |
I feel like drizzle: https://orm.drizzle.team/docs/operators#exists |
Related: #5046 |
I'm wondering @nikolasburk , is this now on the roadmap? I can honestly not understand why this feature is missing... Also note when using the
|
This function have on prisma-binding, it's very helpful, so I thought would be a good idea to insert on the new prisma client.
This functions returns a boolean, you are able to set as many filters (like where from findMany) as you want, if all pass is going to return true, if one fail it's going to return false.
There are some images to help understand on this issue: prisma/prisma-client-js#469.
The text was updated successfully, but these errors were encountered: