mysql - Crear o actualizar una relación de uno a muchos en Prisma
Estoy tratando de actualizar una relación de uno a muchos en Prisma. Mi esquema se ve así
model A_User {
id Int @id
username String
age Int
bio String @db.VarChar(1000)
createdOn DateTime @default(now())
features A_Features[]
}
model A_Features {
id Int @id @default(autoincrement())
description String
A_User A_User? @relation(fields: [a_UserId], references: [id])
a_UserId Int?
}
Estoy intentando agregar un par de nuevas funciones al usuario con id: 1, o actualizarlas si ya están allí.
Estoy tratando de hacer algo como
const post = await prisma.a_User.update({
where: { id: 1},
data: {
features: {
upsert: [
{ description: 'first feature'},
{ description: 'second feature'}
]
}
}
})
El compilador no está contento, me lo dice
Type '{ features: { upsert: { description: string; }[]; }; }' is not assignable to type '(Without<A_UserUpdateInput, A_UserUncheckedUpdateInput> & A_UserUncheckedUpdateInput) | (Without<...> & A_UserUpdateInput)'.
Object literal may only specify known properties, and 'features' does not exist in type '(Without<A_UserUpdateInput, A_UserUncheckedUpdateInput> & A_UserUncheckedUpdateInput) | (Without<...> & A_UserUpdateInput)'.ts(2322)
index.d.ts(1572, 5): The expected type comes from property 'data' which is declared here on type '{ select?: A_UserSelect; include?: A_UserInclude; data: (Without<A_UserUpdateInput, A_UserUncheckedUpdateInput> & A_UserUncheckedUpdateInput) | (Without<...> & A_UserUpdateInput); where: A_UserWhereUniqueInput; }'
(property) features: {
upsert: {
description: string;
}[];
}
No puedo resolver cómo hacerlo ni puedo encontrar ayuda clara en la documentación. ¿Alguna idea sobre cómo implementarlo o dónde puedo encontrar algunos ejemplos?
Respuesta #1
Estoy proporcionando mi solución basándome en las aclaraciones que proporcionaste en los comentarios. Primero haría los siguientes cambios a tu Esquema.
Cambiando el esquema
model A_User {
id Int @id
username String
age Int
bio String @db.VarChar(1000)
createdOn DateTime @default(now())
features A_Features[]
}
model A_Features {
id Int @id @default(autoincrement())
description String @unique
users A_User[]
}
Notablemente, la relación entre A_User y A_Features ahora es de muchos a muchos. Así que un solo registro de A_Features puede estar conectado a muchos registros de A_User (así como lo contrario).
Además, A_Features.description ahora es único, por lo que es posible buscar de manera única una determinada característica usando solo su descripción.
Puedes leer la Guía de Prisma sobre Relaciones para aprender más sobre las relaciones muchos a muchos.
Escribiendo la consulta de actualización
Nuevamente, basándonos en la aclaración que proporcionaste en los comentarios, la operación de actualización hará lo siguiente:
Sobrescribir las
featuresexistentes en un registroA_User. Por lo tanto, cualquierfeaturesanterior será desconectado y reemplazado por los nuevos proporcionados. Tenga en cuenta que lasfeaturesanteriores no se eliminarán de la tablaA_Features, sino que simplemente se desconectarán de la relaciónA_User.features.Cree las nuevas funciones proporcionadas que aún no existen en la tabla
A_Features, y Conecte las funciones proporcionadas que ya existen en la tablaA_Features.
Puedes realizar esta operación utilizando dos consultas update separadas. La primera actualización Desconectará todas las features previamente conectadas para el A_User proporcionado. La segunda consulta Conectará o Creará las features recién proporcionadas en la tabla A_Features. Finalmente, puedes usar la API de transacciones para asegurarte de que ambas operaciones ocurran en orden y juntas. La API de transacciones garantizará que si hay un error en alguna de las dos actualizaciones, ambas fallarán y serán revertidas por la base de datos.
//inside async function
const disconnectPreviouslyConnectedFeatures = prisma.a_User.update({
where: {id: 1},
data: {
features: {
set: [] // disconnecting all previous features
}
}
})
const connectOrCreateNewFeatures = prisma.a_User.update({
where: {id: 1},
data: {
features: {
// connect or create the new features
connectOrCreate: [
{
where: {
description: "'first feature'"
}, create: {
description: "'first feature'"
}
},
{
where: {
description: "second feature"
}, create: {
description: "second feature"
}
}
]
}
}
})
// transaction to ensure either BOTH operations happen or NONE of them happen.
await prisma.$transaction([disconnectPreviouslyConnectedFeatures, connectOrCreateNewFeatures ])
Si quieres una mejor idea de cómo funcionan connect, disconnect y connectOrCreate, lee la sección Nested Writes del artículo sobre consultas de relaciones de Prisma en la documentación.
