首页 > 解决方案 > 在 Prisma 中创建或更新一对多关系

问题描述

我正在尝试更新 Prisma 中的一对多关系。我的架构看起来像这样

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?
}

我正在尝试向 id: 1 的用户添加一些新功能,或者如果它们已经存在则更新它们。

我正在尝试做类似的事情

const post = await prisma.a_User.update({
        where: { id: 1},
        data: { 
            features: {
                upsert: [
                    { description: 'first feature'},
                    { description: 'second feature'}
                ]
            }
        }
    })

编译器不高兴,它告诉我

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;
    }[];
}

我无法弄清楚如何去做,也无法在文档中找到明确的帮助。关于如何实现它或在哪里可以找到一些示例的任何想法?

标签: mysqltypescriptprisma

解决方案


根据您在评论中提供的说明提供我的解决方案。首先,我将对您的架构进行以下更改。

更改架构

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[]
}

A_User值得注意的是,和之间的关系A_Features现在是多对多的。因此,一条A_Features记录可以连接到多A_User条记录(反之亦然)。

此外,A_Features.description现在是唯一的,因此可以仅使用它的描述来唯一地搜索某个功能。

您可以阅读Prisma 关系指南以了解有关多对多关系的更多信息。

编写更新查询

同样,根据您在评论中提供的说明,更新操作将执行以下操作:

  • 覆盖features记录中的现有内容A_User。因此,任何以前features的都将断开连接并替换为新提供的。请注意,前一个features不会从A_Features表中删除,但它们只会与 关系断开连接A_User.features

  • 创建表中尚不存在的新提供的特征A_Features,并连接表中已存在的提供的特征A_Features

您可以使用两个单独的update查询来执行此操作。第一次更新将断开所有先前连接features的提供的A_User. 第二个查询将连接或创建新提供featuresA_Features表。最后,您可以使用事务 API来确保两个操作按顺序一起发生。事务 API 将确保如果两个更新中的任何一个出现错误,那么两个更新都会失败并被数据库回滚。


//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 ])

如果您想更好地了解如何工作connect,请阅读文档中Prisma 关系查询文章的嵌套写入部分。disconnectconnectOrCreate


推荐阅读