Handling Mongoose Populated Fields in GraphQL

前端 未结 2 1585
陌清茗
陌清茗 2021-02-06 09:16

How do I represent a field that could be either a simple ObjectId string or a populated Object Entity?

I have a Mongoose Schema that represents a \'Device t

相关标签:
2条回答
  • 2021-02-06 09:51

    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

    0 讨论(0)
  • 2021-02-06 09:57

    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.js
    
    import { 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.

    0 讨论(0)
提交回复
热议问题