Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upsert new record in Prisma without an ID?

I'm using Prisma (https://www.prisma.io) as ORM. I want to check for duplicates when store data and, if not exists, create a new record.

I thought I could do that with upsert method provided by Prisma and available in the generated client, but the where clause of that method only works with id (or @unique fields), but if the record doesn't exist, there isn't any id to provide.

I provide an example of the problem.

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();

After creation there is a database with three Systems without performances. I'm trying to insert a new SystemPerformance if there aren't any that have same date and same System. I have tried

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

But an exception is thrown:

UnhandledPromiseRejectionWarning: Error: Variable '$where' expected value of type 'SystemPerformanceWhereUniqueInput!' but got: {"system":{"name":'s1'},"date":"2019-03-12T00:01:06.000Z"}. Reason: 'system' Field 'system' is not defined in the input type 'SystemPerformanceWhereUniqueInput'

The only solution I have found is check for existence and then update or create, but I wanted to do it with 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
  }
})

Is there a way to do that with upsert?

like image 331
Jose Ángel de Pascual Viciana Avatar asked Mar 28 '19 18:03

Jose Ángel de Pascual Viciana


People also ask

How do I add new features to Prisma?

If you're trying to add new features, and update specific ones, you would need to specify how Prisma can find an old feature (if it exists) to update that one.

Can Prisma tell me what options are available when passing objects?

I imagine the object you're passing to data takes a different set of options than you are specifying; if you can inspect the TypeScript types, Prisma will tell you exactly what options are available.

What is upsert in Prisma?

The table contains the values suggested in the original INSERT command (that conflicted with the existing table values). Note: If you are connecting to your database with Prisma client, you can perform upsert operations using the dedicated upsert operation. For our examples, suppose that we have a table called director.


1 Answers

The fields in where need to be unique.

If you can make some field, let's say date @unique (date: DateTime! @unique), and use that for your where in the upsert, I think it would work (tested on my local)

like image 193
Antoine Avatar answered Sep 25 '22 18:09

Antoine