typescriptmongoosegraphqlapolloexpress-graphql

How to structure nested lists of objects in GraphQL typeDefs


I have a type user which will contain an array of associated objects which are also a type which is defined. I am trying to figure out the best way to handle input types when creating objects like this with nested object types, I had defined the input type to contain a field children: [childtype] but this throws an error.

type user {
    _id: ID!
    user_name: String!
    email: String!
    password: String!
    children: [child1]!
    created: String!
}

type child1 {
    _id: ID!
    user_id: ID!
    name: String!
    children: [child2]!
    active: Boolean!
}

type child2 {
    _id: ID!
    user_id: ID!
    name: String!
    active: Boolean!
}

I have read up on it and it makes sense why there is a distinction between the input types and regular types. My question is what is the best practice here? I had thought that in document stores like MongoDB it was fairly common to nest documents like this. Ideally I would have wanted to be able to store the entire child document within the parent, which seems straightforward to do in the case where the child is being created along with the parent, or it is being created at the moment it is being stored within the parent. However, another part of my project will involve passing child documents from one parent to another. In this case, will I have to essentially destroy this child and recreate it in the new parent, or is there a way around this? This is my first time using GraphQL and MongoDB so I could be misunderstanding something very simple here.


Solution

  • A couple things:

    1. It's not customary to expose foreign keys in a GraphQL schema. Instead you just include a reference to the type itself. Also note that it's customary to capitalize Types but lowercase fields.

    For example your child1 and child2 types can be:

    type Child1 {
        _id: ID!
        user: User
        name: String!
        children: [Child2]!
        active: Boolean!
    }
    
    type Child2 {
        _id: ID!
        user: User
        name: String!
        active: Boolean!
    }
    
    1. You're correct that if you nest Child1 objects inside a User document (and further nest Child2 documents within the Child1 subdocuments then you'll need to delete from one document and add to another when passing those children between users. Make sure to do these moves within a transaction to avoid losing children or duplicating them during a move.