Búsqueda de sitios web

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 features existentes en un registro A_User. Por lo tanto, cualquier features anterior será desconectado y reemplazado por los nuevos proporcionados. Tenga en cuenta que las features anteriores no se eliminarán de la tabla A_Features, sino que simplemente se desconectarán de la relación A_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 tabla A_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.

Artículos relacionados