Support for more conditions in findOne
See original GitHub issueProblem
I think Prisma should support “nested where” query syntax. This is where two or more tables that are joined both have a where
clause against them.
For example, let’s say I’m building a CRM where a User
has many Contact
s and a Contact
can have many Note
s:
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
contacts Contact[]
}
model Contact {
id Int @default(autoincrement()) @id
user User @relation(fields: [userId], references: [id])
userId Int
name String?
email String?
notes Note[]
}
model Note {
id Int @default(autoincrement()) @id
contact Contact @relation(fields: [contactId], references: [id])
contactId Int
text String
}
In the simplest case I want to pull a note by ID, but only if the proper user owns that note. So let’s say the user is ID 123
and they want to view note 456
. In regular SQL I might do something like
SELECT Note.*
FROM Note INNER JOIN Contact ON Note.contactId = Contact.id
WHERE Note.id = 456 AND Contact.userId = 123
So if the Note.id
is correct, but the proper user doesn’t own that note, this will return null
. Right now when using Prisma I need to manually add a conditional to check the status of that ID, something like:
const note = await db.note.findOne({
where: { id },
include: { contact: { select: { userId: true } } },
})
if (note.contact.userId === currentUser.id) {
return note
} else {
return null
}
(Notice that if I want this function to only return the note
and not included contact
detail, I also need to delete note.contact
).
Suggested solution
Similar to the ability to add select
and include
objects to relations, allowing setting a where
object that could add that nested where
. Then the above code then becomes a single statement:
return db.note.findOne({
where: { id },
include: { contact: { where: { userId: currentUser.id } } }
})
(In this case I would still need to delete the included note.contact
in order to only return the note
data.)
Issue Analytics
- State:
- Created 3 years ago
- Comments:14 (9 by maintainers)
Question: why is this uniqueness constraint part of
findOne
anyway? This isn’t a limitation of SQL…are you trying to optimize something in the code itself? Why not just callfindMany
behind the scenes and then return the first result?This is what Rails ActiveRecord does—
find
(equivalent tofindOne
) is just usingwhere
(equivalent tofindMany
) behind the scenes and then addingLIMIT 1
so you only ever get 1 result. If it’s not the one you were expecting then you weren’t selecting by a unique column, but it doesn’t force you to use a unique column, that’s up to you.Yeah, I actually agree with you here. I will raise this internally to the team 😃