如何在没有ID的情况下在Prisma中插入新记录?

29

我正在使用Prisma (https://www.prisma.io) 作为ORM。我希望在存储数据时检查是否存在重复记录,如果不存在,则创建新记录。

我认为可以使用Prisma提供的upsert方法来解决此问题,并在生成的客户端中使用该方法,但是该方法的where子句仅适用于id(或@ unique字段),但如果记录不存在,则没有任何id可提供。

以下是一个示例问题。

datamodel.prisma

type System {
  id: ID! @unique
  performances: [SystemPerformance!]! @relation(name: "PerformanceBySystem" onDelete: CASCADE)
  name: String! @unique
}

type SystemPerformance {
  id: ID! @unique
  system: System! @relation(name: "PerformanceBySystem")
  date: DateTime!
  perf1: Float
  perf2: Float
}

seed.js

const { prisma } = require('./generated/prisma-client');
async function main(){
  await prisma.createSystem({
    name: 's1',
  });
  await prisma.createSystem({
    name: 's2',
  });
  await prisma.createSystem({
    name: 's3',
  });
}
main();

创建后,有一个没有性能的数据库。如果不存在与相同日期和相同系统的SystemPerformance,则尝试插入新的 SystemPerformance。我已经尝试过。

const { prisma } = require('./prisma/generated/prisma-client');

const perf = await prisma.upsertSystemPerformance({
       where: {
         system: {name: 's1'},
         date: "2019-03-12T00:01:06.000Z"
       },
       update: {
         perf1: 13.45,
         perf2: 18.93
       },
       create: {
        system: {
            connect: { name: 's1' }
        },
        date: "2019-03-12T00:01:06.000Z",
        perf1: 13.45,
        perf2: 18.93
       }
})

但是抛出了异常:

UnhandledPromiseRejectionWarning: Error: 变量 '$where' 期望类型为 'SystemPerformanceWhereUniqueInput!',但实际得到: {"system":{"name":'s1'},"date":"2019-03-12T00:01:06.000Z"}。原因:输入类型 'SystemPerformanceWhereUniqueInput' 中未定义 'system' 字段

我找到的唯一解决方案是检查存在性,然后进行更新或创建,但我想用 upsert 实现它。

let check = await prisma.$exists.SystemPerformance({
            system: {name: 's1'},
            date: "2019-03-12T00:01:06.000Z"
        });
let perfo;
if (check){
  const sysPerf = await prisma.systemPerformances({where:{system: {name: 's1'}, date: "2019-03-12T00:01:06.000Z"}})
            .$fragment(`
            {
                id
            }
            `);
  perfo = await prisma.updateSystemPerformance({
    where: {id: sysPerf[0].id},
            data: {
              perf1: 13.45,
              perf2: 18.93
            }
   })
}
else {
  perfo = await prisma.createSystemPerformance({
    system: {
      connect: { name: 's1' }
    },
    date: "2019-03-12T00:01:06.000Z",
    perf1: 13.45,
    perf2: 18.93
  }
})

使用 upsert 有办法做到这一点吗?


2
Upsert在“where”子句中仅接受唯一字段作为输入。我担心您必须使用解决方法,在查询记录后根据记录是否存在使用upsert或update / create。 - Raeesaa
1
我很担心这一点。我问是否有更好的解决方案。谢谢你的回答。 - Jose Ángel de Pascual Viciana
1
我使用的一个不太正规的方法,但对我很有效,就是使用一个不存在的 id 作为标记值:where: { id: id ?? "不存在" } - Kashif Nazar
4个回答

18

where 中的字段需要唯一。

如果您可以创建一些字段,比如说 date @unique (date: DateTime! @unique),然后在 upsert 中使用该字段作为 where 条件,我认为它会起作用(已在本地测试)。


9
如果您还没有答案,我使用了 @Antoine 的回答以及另一个 Stack Overflow 的回答。
model Likes {
  id         String     @id @unique @default(uuid())
  user_id    String
  tag        String
  auth_user  AuthUser   @relation(references: [id], fields: [user_id], onDelete: Cascade)

  @@unique([user_id, tag], name: "user_id_tag")  // <-- this is the unique constraint
  @@index([user_id])
  @@map("likes")
}

然后我可以通过以下方式进行upsert操作:
prisma.likes.upsert({
    where: {
        user_id_tag: { // <-- And this bit is important
            user_id: user.userId,
            tag: tag.tag
        }
    },
    update: {},
    create: tag
})

2
where: {
    id: sysPerf[0].id ? sysPerf[0].id : 0
},

7
您的回答可以通过添加有关代码功能及其如何帮助问题提出者的更多信息来改进。 - Tyler2P
它可以在Mariadb上运行。 - Sacru2red

0
如果使用 Mongo,您可以使用 bson-objectid 包添加 ObjectId:
import ObjectId from "bson-objectid";

providers: {
        upsert: data.item?.map((item: Prisma.ItemCreateInput) => ({
          where: {
            id: item.id || ObjectId().toString(),
          },
          update: {
            // ...data
          },
          create: {
            // ...data
          },
        })),
      },
}

否则,您需要提供自己的uuid或唯一标识符,该标识符将被传递。
另请参阅https://github.com/prisma/prisma/issues/6718

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接