Danil Kolesnikov
06/07/2021, 1:28 AMsome and every with a more complex use-case for filtering on relations. Is this a bug with Prisma or I am not using it correctly?
Goal: Given an organization id, provide all forms associated with it.
Reality: when using every clause the filtering doesn't work as expected, we get all forms from all organization. When using some, we get forms from only that organization (expected).
Code:
prisma.applicationFormConfig.findMany({
where: { organizations: { every: { id: organization.id } } },
})// yield all forms from all organization
prisma.applicationFormConfig.findMany({
where: { organizations: { some: { id: organization.id } } },
}),// works as expected
Why? Please help.
More context:
After inspecting SQL, it becomes obvious why, this is raw query for `every`:
prisma:query SELECT "public"."ApplicationFormConfig"."id", ... FROM "public"."ApplicationFormConfig" WHERE ("public"."ApplicationFormConfig"."id")
NOT IN (SELECT "t0"."A" FROM "public"."_ApplicationFormConfigToOrganization" AS "t0"
INNER JOIN "public"."Organization" AS "j0" ON ("j0"."id") = ("t0"."B")
WHERE ((NOT "j0"."id" = $1) AND "t0"."A" IS NOT NULL)) OFFSET $2
look at WHERE ((NOT "j0"."id" = $1) which will yield all other records. $1 is the organization.id in the prisma query.
When using some, it is fixed:
WHERE ("j0"."id" = $1
Schema:
model ApplicationFormConfig {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
...
organizations Organization[]
}
model Organization {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
...
applicationFormConfigs ApplicationFormConfig[]
...
}Ryan
06/07/2021, 8:56 AMRyan
06/07/2021, 8:57 AMsome means at least and every means all.Danil Kolesnikov
06/07/2021, 4:04 PMorganization.id . Are you saying that every negates the filtering clause? Because thats what is happening. All applicationFormConfig for ALL Organization are returned. But we are looking for only the forms from a particular organization id.
prisma.applicationFormConfig.findMany({
where: { organizations: { every: { id: organization.id } } },
})// yield all forms from all organizationRyan
06/08/2021, 4:48 AMsome is the way to go. some will find at least one record matching the criteria where as every will check for all records that match the criteria and only return those in which all relations match.
If you’re familiar with JavaScript’s some and every, then this would be easier to understand.Danil Kolesnikov
06/08/2021, 5:58 PMevery and there is 1 match in the table, it will return all records from the table and not only the ones that match. Correct?Ryan
06/09/2021, 6:29 AMmodel User {
id Int @id @default(autoincrement())
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
user User? @relation(fields: [userId], references: [id])
userId Int?
}
I seed this with the following data:
await prisma.user.create({
data: {
name: 'user 1',
posts: {
create: [{ title: 'prisma ORM' }, { title: 'prisma ORM again' }],
},
},
})
await prisma.user.create({
data: {
name: 'user 2',
posts: {
create: [{ title: 'prisma ORM' }, { title: 'another one again' }],
},
},
})
await prisma.user.create({
data: {
name: 'user 3',
},
})
If I query for the following with `every`:
await prisma.user.findMany({
where: { posts: { every: { title: { contains: 'prisma' } } } },
})
I will get user 1 and user 3 back as the match the criteria. One has all posts with prisma while the other has no posts.
In your case, you want at least 1 record that matches so you need to use some.Danil Kolesnikov
06/09/2021, 3:33 PMevery: { id: organization.id } all rows get returned no matter the organization with filter not working but changing to some fixes it. Why does that happen? a bug?Danil Kolesnikov
06/09/2021, 3:34 PMDanil Kolesnikov
06/09/2021, 3:35 PMsome do? Will that yield the same result?Ryan
06/09/2021, 4:00 PMoh wow, I am confused now because in my query withÂWould it be possible to send a simple reproduction so that I can check? Also as per your use case you need all rows get returned no matter the organization with filter not working but changing toÂevery: { id: organization.id } fixes it. Why does that happen? a bug?some
some and not every as I had said before.
So in your case, all posts would get returned. I think the MDN articles you’ve sent confused me since JS functions return a boolean value, not sure how that translates to relational filtering in Prisma.Yeah
every makes sure that only those items are sent back in which each value of the relation matches the criteria. The JS function returns a boolean but the concept is same as Prisma returns the values that match instead of the boolean.
some would yield User 1 and User 2 as User 2 has a post that matches with Prisma.