8

How do I generate ID automatically when I use AppSync and DynamoDB as the database source?

I have a type looking like below

type Post {
    id: ID!
    creator: String!
    createdAt: String!
    like: Int!
    dislike: Int!
    frozen: Boolean!
}

and input looking like below

input CreatePostInput {
    id: ID!
    creator: String!
    createdAt: String!
    like: Int!
    dislike: Int!
    frozen: Boolean!
}

and my mutation is obviously the combination of the two

createPost(input: CreatePostInput!): Post

However, when I make inserts I have to do something like below

mutation createPost{
  createPost(input:{
    id:2
    creator:"some creator"
    createdAt:"some date"
    like:0
    dislike:0
    frozen:false
  }){
    id
    creator
    createdAt
    like
    dislike
    frozen
  }
}

There is no way I can insert a post without having to know what the id is up to right now. Is there a way I can provide null or any random id and DynamoDB or AppSync automatically create the next index before inserting into the table?

Error generated when I update the input CreatePostInput to not accept any ID

{
  "data": {
    "createPost": null
  },
  "errors": [
    {
      "path": [
        "createPost"
      ],
      "data": null,
      "errorType": "DynamoDB:AmazonDynamoDBException",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "One or more parameter values were invalid: Type mismatch for key id expected: S actual: NULL (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 629QEM7MH9BRAJ9MHU3FM1S0U3VV4KQNSO5AEMVJF66Q9ASUAAJG)"
    }
  ]
}

My Resolver Template

{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        ## If object "id" should come from GraphQL arguments, change to $util.dynamodb.toDynamoDBJson($ctx.args.id)
        "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
forJ
  • 4,309
  • 6
  • 34
  • 60

2 Answers2

7

First, update the createPost resolver as:

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
  },
  "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
  "condition": {
    "expression": "attribute_not_exists(#id)",
    "expressionNames": {
      "#id": "id",
    },
  },
}

Then, remove the id field from your CreatePostInput input type:

input CreatePostInput {
  creator: String!
  createdAt: String!
  like: Int!
  dislike: Int!
  frozen: Boolean!
}

Save both the changes and you should be done.

If you're the one of seeing-is-believing guys like me, take a look at this egghead.io video.

vahdet
  • 6,357
  • 9
  • 51
  • 106
0

You can auto generate a UUIDv4 using the $util.autoId() velocity helper function. For example, you can write a createPost resolver that uses a server-side generated id like this.

{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
mparis
  • 3,623
  • 1
  • 17
  • 16
  • sorry I forgot to include that part. My resolver looks exactly same as what you have written. Do you have any suggestions what might be going wrong? – forJ Jul 13 '18 at 04:45
  • If you are using $util.autoId() you should not have to pass an id as part of the input. Can you try deleting the Id field from the create input and call the mutation? If you aren't getting an I'd generated for you please make sure you are using $util.autoId() – mparis Jul 13 '18 at 22:53
  • yes I have tried that too but it returns the error that I have specified in the question update. Can you please confirm for me if you are using the same methodology in your `AppSync` application and `$util.autoId()` is working for you? – forJ Jul 14 '18 at 06:21
  • I have pasted that on my question – forJ Jul 14 '18 at 08:24