Regarding prisma 3.14 and MongoDB: I'm trying to g...
# orm-help
m
Regarding prisma 3.14 and MongoDB: I'm trying to get embedded documents working with mongodb, using prisma 3.14 and the structure according to the schema provided in the release notes of prisma 3.10 ( https://github.com/prisma/prisma/releases/tag/3.10.0 ). Running a query against the db I get an error telling me
Copy code
type EmailMessage { .... error: Model declarations have to be indicated with the `model` keyword`
same error also for EmailSubject my schema:
Copy code
model Email {
  id            String @id @map("_id") @db.ObjectId
  name          String @unique
  emailMessage  EmailMessage
  emailSubject  EmailSubject
  receiverGroup Receiver[]
  isActivated   Boolean @default(value: true)
  role          String
  btnName       String
}

type EmailMessage {
  id        String
  messageDe String
  messageEn String
}

type EmailSubject {
  id        String
  subjectDe String
  subjectEn String
}

type Receiver {
  id        String
  email     String
  firstName String
  lastName  String
}
What am I doing wrong regarding these embedded documents ? Is there support for embedded document lists but not for embedded documents ?
n
I tried it and it's working as expected Here's the schema file
Copy code
generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native"]
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

model Email {
  id            String       @id @default(auto()) @map("_id") @db.ObjectId
  name          String       @unique
  emailMessage  EmailMessage
  emailSubject  EmailSubject
  receiverGroup Receiver[]
  isActivated   Boolean      @default(value: true)
  role          String
  btnName       String
}

type EmailMessage {
  id        String
  messageDe String
  messageEn String
}

type EmailSubject {
  id        String
  subjectDe String
  subjectEn String
}

type Receiver {
  id        String
  email     String
  firstName String
  lastName  String
}
Query
Copy code
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

async function main() {
  const response = await prisma.email.create({
    data: {
      btnName: "btnName",
      emailMessage: {
        id: "1",
        messageDe: "messageDe",
        messageEn: "messageEn",
      },
      emailSubject: {
        id: "1",
        subjectDe: "subjectDe",
        subjectEn: "subjectEn",
      },
      name: "name",
      role: "role",
      isActivated: true,
      receiverGroup: {
        id: "1",
        email: "<mailto:email@email.com|email@email.com>",
        firstName: "firstName",
        lastName: "lastName",
      },
    },
  });

  console.log(response);
}

main()
  .catch((e) => {
    throw e;
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
Response:
Copy code
{
  emailMessage: { id: '1', messageDe: 'messageDe', messageEn: 'messageEn' },
  emailSubject: { id: '1', subjectDe: 'subjectDe', subjectEn: 'subjectEn' },
  receiverGroup: [
    {
      id: '1',
      email: '<mailto:email@email.com|email@email.com>',
      firstName: 'firstName',
      lastName: 'lastName'
    }
  ],
  id: '627cfd4cb10b4047615b03f7',
  name: 'name',
  isActivated: true,
  role: 'role',
  btnName: 'btnName'
}
There is support for both embedded documents and embedded documents list
In your schema file I just added
@default(auto())
in Email model in id field
m
Thank you very much, so this seems to be working with newly created documents, I tried to query all documents from the DB created with prisma1, that didn't work. I want to keep my existing data. 🙂
Copy code
import { PrismaClient } from '@prisma/client'
 const prisma = new PrismaClient()
 
 async function main() {
   await prisma.$connect()
   const emails = await prisma.email.findMany()
   console.log(emails)
 }
 
 main()
   .catch(console.error)
   .finally(() => prisma.$disconnect())
Is there a pendant for a custom dbName / Collection ? My DB is called emaildb_default and the collection emails. In the P1 model I had
Copy code
type Email @db(name: "emails") {...
Threw errors in P3.14 when I tried that
n
If your collection name is emails then it has to be defined as
model
in schema file,
type
keyword is reserved for embedded document and shouldn't be used for defining collection.
m
Ah, so it is not possible to define
Copy code
model Email @db(name: "emails") {...
using a custom name for the collection ?
all our P1 data are stored in the emails collection
something like
Copy code
datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
  collection = "emails"
}
would be nice
n
You could do that this way
Copy code
model Email {

@@map("emails")
}
m
thank you very much 🙂 is it mandatory to use mongodb 4.2+ ? I'm currently using 3.6
m
I found my problem:
Copy code
nexus-plugin-prisma@0.35.0" has incorrect peer dependency "@prisma/client@2.23.x"
When I pin the prisma client to 2.23.0 I get these model declaration errors. Do you have any idea how I could resolve this ? I really need nexus-plugin-prisma.
n
Ah, nexus-plugin-prisma is deprecated in favour of nexus-prisma
m
yap 🙂 and nexus-prisma is not ready for production which we are using
btw: when I do a findMany() on my email prisma complains about missing required id field
Copy code
const emails = await prisma.email.findMany()
  Error converting field "id" of expected non-nullable type "String", found incompatible value of "null".
is this a bug ? normally findMany() should just return all entries...
in my case findMany only works with
Copy code
prisma.email.findMany({ select: { id: true } })
which returns
Copy code
[
  { id: '62399af4054ec80008386eee' },
  { id: '62399af4054ec80008386ef6' },
  { id: '62399af4054ec80008386eec' },
  { id: '62399af4054ec80008386eff' },
  { id: '62399af4054ec80008386f00' },
  { id: '62399af4054ec80008386f05' },
  { id: '62399af4054ec80008386f08' },
  { id: '62399af4054ec80008386f0b' },
  { id: '62399af4054ec80008386ef1' },
  { id: '62399af4054ec80008386efb' },
  { id: '62399af4054ec80008386f0e' },
  { id: '62399af4054ec80008386f11' },
  { id: '62399af4054ec80008386f16' },
  { id: '62399af4054ec80008386f14' },
  { id: '62399af4054ec80008386f15' },
  { id: '62399af4054ec80008386ef4' },
  { id: '626fe6e10b5bca0008210a5b' },
  { id: '626fe6e10b5bca0008210a5e' },
  { id: '626fe6e10b5bca0008210a61' }
]
n
Are there any records which has id as null?
m
nope
the receiverGroup isn't present by default, it is optional and filled before an email actually is sent, but this hasn't been a problem
the primary key id and unique name are present in all datasets
I think this might actually be a bug, id shouldn't be exspected in plain findMany(), but it seems to be anyway:
Copy code
meta: { field: 'id', expected_type: 'String', found: 'null' }
even if I remove the receiverGroup from the model the error stays the same
Copy code
db.emails.find({_id: null})
   .limit(100)

-> No records found
n
This should definitely work
Copy code
const emails = await prisma.email.findMany()
It should return all the emails. Can you create a Bug Report for it here. I think if you add all the fields in select clause then it will work for now.
m
Did you try this on a existing database created by prisma1 ? Maybe this works for newly created datasets and for what reason ever not for datasets created by P1. 😉
thank you for the hint, it brought a little light in this thing: If I select a or more embedded fields I get the error with the filter:
Copy code
const emails = await prisma.email.findMany({
    select: {
      id: true,
      name: true,
      isActivated: true,
      role: true,
      btnName: true,
    },
  });
works, but
Copy code
const emails = await prisma.email.findMany({
    select: {
      id: true,
      name: true,
      emailMessage: true,
      isActivated: true,
      role: true,
      btnName: true,
    },
  });
does not! ;)
n
I don't think it matters how data was created as long as it adheres to database schema. But definitely, this is related to P1 -> P2 migration
m
emailMessage is an embedded field
n
what error do you get?
m
so are emailSubject and receiverGroup
Copy code
Error converting field "id" of expected non-nullable type "String", found incompatible value of "null"
 code: 'P2032',
  clientVersion: '3.14.0',
  meta: { field: 'id', expected_type: 'String', found: 'null' }
I tried adding
Copy code
@id @map("_id") @db.ObjectId
to the id String field in the nested type, but that doesn't work, I thought maybe the id field has to be defined like in the main model, but this doesn't seem to be the case
eureka! 😉 the id field in the embedded type needs additional mapping, but NOT @id, it needs
Copy code
@map("_id"):

type EmailMessage {
  id        String @map("_id")
  messageDe String
  messageEn String
}

type EmailSubject {
  id        String @map("_id")
  subjectDe String
  subjectEn String
}

type Receiver {
  id        String @map("_id")
  email     String
  firstName String
  lastName  String
}
and with THAT findMany() also works! 🙂
maybe this could find its way into the documentation, small thing, can cause lots of lost time if missing 🙂
I'm not sure if adding
@db.ObjectId
is neccessary, it also works
n
Amazing! So you can fetch embedded documents with select clause, right? But this still gives you an error?
Copy code
const emails = await prisma.email.findMany()
m
nope, this also works now
🙂
it was the missing
@map("_id")
n
The error message could definitely be improved, I'll pass this feedback! 🙌
m
thank you very much for your help! 🙂
🙌 1
👍 1