GraphQL Mutation how to make fields optional to update fields only by selection and generate schema

733 Views Asked by At

I have a graphql mutation defined as follows

type Mutation {
    updateParts(
      partId: String!
      parts: PartRequest!
    ): UpdatePartsResponse!
}

input PartRequest {
    name: String!
    image: Strings!
    boltTypes: [Bolts]!
}

input Bolts {
    code: String!
    metadata: String!
}

Mhy requirement was to update fields upon selection as following.

  • update all
mutation {
  updateParts(
    partId: "0x1223"
    parts: {
      name: "some"
      image: "dark.png"
      boltTypes: [
        { code: "A", metadata: "B" }
      ]
    }
  ) 
  }
}
  • Update by selection: name only
mutation {
  updateParts(
    partId: "0x1223"
    parts: {
      name: "some"
    }
  ) 
  }
}
  • Update by selection: parts only
mutation {
  updateParts(
    partId: "0x1223"
    parts: {
      boltTypes: [
        { code: "A", metadata: "B" }
      ]
    }
  ) 
  }
}

How to construct a schema to achieve this ?

2

There are 2 best solutions below

0
ThisaruG On

You have to make your arguments optional to achieve this. Try the following schema:

type Mutation {
    updateParts(
        partId: String!
        parts: PartRequest!
    ): UpdatePartsResponse!
}

input PartRequest {
    name: String
    image: String
    boltTypes: [Bolts!]
}

input Bolts {
    code: String!
    metadata: String!
}

Notice the PartRequest input object. The fields are nullable. That means you don't necessarily need to provide a value for those arguments. The ! means they are NON_NULL types, which means you have to provide a value for those always.

I have made the boltTypes field type to [Bolts!] which means the boltTypes field can be null, but the array cannot have null as an element.

0
Risith Ravisara On

In Java, If you use the Netflix DGS framework, You can use DgsDataFetchingEnvironment to get selected properties in Input object as a LinkedHashMap.

@DgsMutation
public Customer updateParts(DgsDataFetchingEnvironment dfe, @InputArgument String partId, @InputArgument PartRequest parts) {
    LinkedHashMap inputData = dfe.getArgument("parts");
    return partsService.updatePartsPartially(inputData);
}

Here PartRequest objects contain all the fields meanwhile LinkedHashMap only contains fields that are defined in the query. Let's say in the query that you only update "name" then PartRequest object "parts" field is null. Then you can't explicitly define whether this field not updated by the query or not. Because null is also an acceptable value.

But if you get the argument from the DgsDataFetchingEnvironment class as LinkedHashMap it only contains "name" field. So you can use it to dynamically update only those columns in the Database.