If I understand your question correctly, the request body may optionally contain an id or be undefined. If the id is present in the request, you want to update the corresponding record. If it isn't, you want to create a new record.
upsert functionality requires a unique identifier that can be used by the database to check whether there is a matching record. The database will then decide what to do. However with an undefined value, prisma cannot work.
You could use a key that will not exist in the database in case the value of id is undefined to make upsert insert the record in this case.
await prisma.profile.upsert({
where: { id: id || '' },
// ...
});
Or you could differentiate the cases and treat them appropriately:
if (id) {
await prisma.profile.update({
where: { id },
data: {
username,
about,
// ...
},
});
} else {
await prisma.profile.create({
data: {
username,
about,
// ...
},
});
}
You might want to think about the case that there is an id given in the body, but it does exist in the database. Do you want the update to fail and reply with an error? Or do you want the database to silently insert? Then use upsert instead of update above.
You can't do it right now in Prisma. There is createMany, updateMany and deleteMany, but no upsertMany. (Docs)
The most efficient way if you need to handle lots of data would probably be something like that:
prisma.$transaction([
prisma.posts.deleteMany({ where: { userId: 1 } }),
prisma.posts.createMany({
{ id: 1, title: 'first', userId: 1 },
{ id: 2, title: 'second', userId: 1 },
{ id: 3, title: 'third', userId: 1 },
}),
]);
So you delete existing records and then recreate them again inside of a transaction.
Depending on the database (and schema) you use, Prisma supports an optional boolean within a createMany call: skipDuplicates, see https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#createmany
Do not insert records with unique fields or ID fields that already exist. Only supported by databases that support ON CONFLICT DO NOTHING.
Prisma doesn't natively support upsertMany.
There is a Feature Request to provide the upsertMany method.
As of now the best approach would be to loop over the data and invoke upsert in the loop along with using $transaction.
Example:
const collection = await prisma.$transaction(
userData.map(cur =>
prisma.cur.upsert({
where: { id: cur.id },
update: {},
create: { id: cur.id },
})
)
)
Here's a reference to $transaction API which should be helpful.
You can use upsert to update multiple objects like the following: In the following example, I am updating a user's profile and upserting multiple addresses by using the map function.
await this.prisma.user.update({
where: {
id: user.id
},
data:{
fullName: saveUserProfileDto?.fullName,
email: saveUserProfileDto?.email,
userAddresses: {
upsert: saveUserProfileDto?.addresses?.map(address => ({
where: {
uuid: address.uuid || ""
},
create: {
uuid: uuidv4(),
country: address.country,
cityTown: address.cityTown,
streetAddress: address.streetAddress,
apartmentSuit: address.apartmentSuit,
},
update: {
country: address.country,
cityTown: address.cityTown,
streetAddress: address.streetAddress,
apartmentSuit: address.apartmentSuit,
}
}))
}
}
});
So you don't need to delete anything before upserting.