Handling Mongoose Populated Fields in GraphQL Handling Mongoose Populated Fields in GraphQL mongoose mongoose

Handling Mongoose Populated Fields in GraphQL


As a matter of fact, you can use union or interface type for linked_device field.

Using union type, you can implement GQAssetType as follows:

// graphql-asset-type.jsimport { GraphQLObjectType, GraphQLString, GraphQLUnionType } from 'graphql'var LinkedDeviceType = new GraphQLUnionType({  name: 'Linked Device',  types: [ ObjectIdType, GQAssetType ],  resolveType(value) {    if (value instanceof ObjectId) {      return ObjectIdType;    }    if (value instanceof Asset) {      return GQAssetType;    }  }});export var GQAssetType = new GraphQLObjectType({  name: 'Asset',  fields: () => ({    name: { type: GraphQLString },    linked_device: { type: LinkedDeviceType },  })});

Check out this excellent article on GraphQL union and interface.


I was trying to solve the general problem of pulling relational data when I came across this article. To be clear, the original question appears to be how to dynamically resolve data when the field may contain either the ObjectId or the Object, however I don't believe it's good design in the first place to have a field store either object or objectId. Accordingly, I was interested in solving the simplified scenario where I keep the fields separated -- one for the Id, and the other for the object. I also, thought employing Unions was overly complex unless you actually have another scenario like those described in the docs referenced above. I figured the solution below may interest others also...

Note: I'm using graphql-tools so my types are written schema language syntax. So, if you have a User Type that has fields like this:

type User {    _id: ID    firstName: String    lastName: String    companyId: ID    company: Company}

Then in my user resolver functions code, I add this:

  User: {   // <-- this refers to the User Type in Graphql    company(u) {   // <-- this refers to the company field      return User.findOne({ _id: u.companyId }); // <-- mongoose User type    },  }

The above works alongside the User resolver functions already in place, and allow you write GQL queries like this:

query getUserById($_id:ID!)     { getUserById(_id:$_id) {    _id    firstName    lastName    company {        name    }    companyId    }}

Regards,

S. Arora