1 year ago

#75382

test-img

izidormaklary

How to use graphql subscriptions on large objects correctly with Apollo?

I am querying a large object with some relational fields (which are also relational sometimes). So I get a result like this:

largeObject{
  field1
  field2
  field3
  children1{
    field1
    field2
    ... and so on
    nestedChildren{
      field1
      field2
      ... and so on
    }
  }
  ... and so on
}

And in order to keep the data up to date I need to use subscriptions, but I don't want to always return the whole object as payload as that would result in a huge query on the backend even on the smallest change.

So my approach was to send back only the changed and the necessary (like ID etc.) fields.

On the backend:

// the typedefs for this object look something like this

type LargeObject{
  field1: ID
  field2: String
  field3: Int
  field4: String
  children1: Children1Type
  ... and so on
} 
type Query{
   largeObjectById(id:ID):LargeObject
}
type Subscription{
  largeObjectChanged(id:ID):LargeObject
}

//and in the resolvers

const largeObjectResolver ={
  Query:{
    ...
  },
  Mutation:{
    async changeField2LargeObject(_, args, context, info){
      // I am using objection
      const largeObject = LargeObject.query()
        .findById(args.id)
        .withGraphFetched(
           {/*...generated graph to have all the queried relational 
             fields*/
           })
        .patch({field2: args.value})
        .returning("*")
        .first()
      
      // but here instead of querying for all the relational fields supposedly needed for 
      // the subscribed, I am just returning the changed fields for the subscription.
      pubsub.publish("LARGE_OBJECT_CHANGED",
        {
          largeObjectChanged:{id:largeObject.id, field2:largeObject.field2}
        })

      return ...
    }
  }

}

After all I subscribe to all the fields on the frontend, and try to filter out the fields that are null (because there were no values published for them)

// the subscription has the same fields as the query
gql`
  subscription LargeObjectChanged{
    // same fields as in query, so basically all the fields
  }
`

But this is still problematic because it will disregard the case when "field2" is actually updated to null.

TLDR: How to update large object only partially using subscription to avoid querying and sending all the relational fields of the object on each Mutation.

graphql

apollo

apollo-server

graphql-subscriptions

0 Answers

Your Answer

Accepted video resources