Prisma1: [Mongo] embedded type data not returned using prisma client

Created on 25 Apr 2019  路  10Comments  路  Source: prisma/prisma1

Describe the bug
I have defined a simple data model containing @embedded types like this:

type User{
    id: ID! @id
    name: String!
    posts: [Post]
}

type Post @embedded {
    id: ID! @id
    text: String!
    comments: [Comment]
}

type Comment @embedded{
    id: ID! @id
    text: String
}

When trying to retrieve the data using the Prisma Client like prisma.users(), only the scalar types and not the embedded types are returned.

To Reproduce

  1. Create a user with posts using prisma.createUser
  2. Validated that the MongoDB contains the correct data
  3. prisma.users() does not return the embedded data

Please see https://github.com/philsch/prisma-bug-demo for a running example.

Expected behavior
The result of Prisma Client contains the embedded data also.

Versions (please complete the following information):

  • Connector: MongoDB
  • Prisma Server: 1.31.0
  • prisma CLI: prisma/1.31.1 (darwin-x64) node-v8.14.1
  • OS: MacOS
bu2-confirmed areconnectomongo kinbug

Most helpful comment

Possibly related issue - I have an embedded type that has a link to other type. I am unable to get a working query for the inner relation.

Example data.model:

type Item{
  id: ID! @id,
  name: [Translation!]!,
}

type Translation @embedded{
  language: Language! @relation(link: INLINE),
  text: String!
}

type Language{
  id: ID! @id,
  code: String! @unique,
}

When I run this query

query{
  items{
    id
    name{
      text
      language{
        code
      }
    }
  }
}

it works fine in the prisma-client, however with nexus-prisma I get en error
"Cannot return null for non-nullable field Translation.language."

Is this related? Is there a workaround?

All 10 comments

I can confirm this

image

Thanks for the detailed information and the well-prepared reproduction :)

You can populate the fields though.

prisma.user({id: "some-id"}).posts()

This is the normal behavior of a MongoDB database. You need to explicitly ask for the embedded documents (So if you don't need them the request is super-fast).

Thanks for pointing out this possibility @SergeiMeza. However, I see some disadvantages in real world use cases especially if a datamodel makes heavy use of embedded scalar lists:

Problem 1: retrieving many embedded elements
In a real project I would need to do something like this to create a local representation of my data:

const user = await prisma.user({id: "some-id"});
const comments = await prisma.user({id: "some-id"}).comments();
const posts = await prisma.user({id: "some-id"}).posts();
// ... do the same call for all other embedded documents

Problem 2: same scenario for retrieving many users
Even more logic is needed when retrieving multiple users and for those multiple users the comments and posts are needed. For this scenario a combination like const users = await prisma.users(); and const comments = await prisma.users().comments(); would be needed.

The code prisma.users().comments() is working, but in a TypeScript context this usage does not seems to be expected:

TS2339: Property 'comments' does not exist on type 'FragmentableArray<User>'.

In summary
I would still see this as a bug (maybe missing feature) as:

  • the current approach forces me to "repeat myself" inside the business logic (explicitly naming the fields) which narrows the benefits of using an ORM
  • retrieving embedded data for a list of elements needs too much own business logic and seems not to be fully supported in a TypeScript context

@SergeiMeza

That is not the expected behaviour. This is a bug that we will need to fix.

Possibly related issue - I have an embedded type that has a link to other type. I am unable to get a working query for the inner relation.

Example data.model:

type Item{
  id: ID! @id,
  name: [Translation!]!,
}

type Translation @embedded{
  language: Language! @relation(link: INLINE),
  text: String!
}

type Language{
  id: ID! @id,
  code: String! @unique,
}

When I run this query

query{
  items{
    id
    name{
      text
      language{
        code
      }
    }
  }
}

it works fine in the prisma-client, however with nexus-prisma I get en error
"Cannot return null for non-nullable field Translation.language."

Is this related? Is there a workaround?

I suspect the problem is on the auto generated client code.

It generates the models as:

var models = [
  {
    name: "Item",
    embedded: false
  },
  {
    name: "Translation",
    embedded: false
  },
  {
    name: "Language",
    embedded: false
  }
];

By switching embedded: false to embedded: true the query returns:

{"id":"5cffe4a6b834740009759c2b","name":"test","posts":[{"id":"5cffe4a6b834740009759c2c","text":"hello","comments":[]}]}
[{"id":"5cffe483b834740009759c29","name":"test","posts":[{"id":"5cffe483b834740009759c2a","text":"hello","comments":[]}]},{"id":"5cffe4a6b834740009759c2b","name":"test","posts":[{"id":"5cffe4a6b834740009759c2c","text":"hello","comments":[]}]}]

I suspect the problem is on the auto generated client code.

It generates the models as:

var models = [
  {
    name: "Item",
    embedded: false
  },
  {
    name: "Translation",
    embedded: false
  },
  {
    name: "Language",
    embedded: false
  }
];

By switching embedded: false to embedded: true the query returns:

{"id":"5cffe4a6b834740009759c2b","name":"test","posts":[{"id":"5cffe4a6b834740009759c2c","text":"hello","comments":[]}]}
[{"id":"5cffe483b834740009759c29","name":"test","posts":[{"id":"5cffe483b834740009759c2a","text":"hello","comments":[]}]},{"id":"5cffe4a6b834740009759c2b","name":"test","posts":[{"id":"5cffe4a6b834740009759c2c","text":"hello","comments":[]}]}]

My models are generated correctly with embedded: true. Problem is when an embedded type has a link to some other type. I suspect the problem is elsewhere in the autogenerated nexus-prisma file, but can't seem to find it, as it has over 20k lines :).

@philsch wondering how you got around this? I think I'm facing the same issue.
Anybody on this or... just on prisma2?

@tiagocpontesp actually my current workaround is to create a GraphQL query that names all needed fields and use prisma.$graphql(query);. This is of course very error-prone, because all projects have basically a copy of the data model. If I change the datamodel I have to adapt all GraphQL queries. Looking forward to get rid of this duplication :)

Any updates on this issue?

Was this page helpful?
0 / 5 - 0 ratings