amplify-cli: AWSJSON update not working correctly

Describe the bug I have a model with the attribute ‘timelines’ set to the type timelines: AWSJSON.

This field is designed to hold an array of objects.

When i create the initial object, everything works as it should do. I first stringify the bject and them push it to the database by updating the parent model table… in this case ‘Event’.

If I then change the object in any way, rather than updating the value in the database, it appends the same object with the new values onto the array.

for example, the first push to timelines with an array with one object in creates the following: Event:

{ 
   title: 'blah',
    timelines: "[{ id: 1, title: 'hello' }]"
}

If i then run the update:

result = await this.amplify.api().graphql(graphqlOperation(updateEvent, { input }));

with the input being:

{ 
   title: 'blah',
    timelines: "[{ id: 1, title: 'test' }]"
}

The resulting change is that the database displays:

{ 
   title: 'blah',
    timelines: "[{ id: 1, title: 'hello' }, { id: 1, title: 'test' }]"
}

Amplify CLI Version 4.18.0

Expected behavior It should behave like any other update operation. if i send an update with the timelines array, the array being send should be the value. I don’t understand why it would append to the array!

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information): MAC OSX Catalina

Additional context I have checked the network tab to make sure the stringified value under timelines is correct, and it is, and so the graphql dynamo system must be dong something.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 3
  • Comments: 28 (9 by maintainers)

Most upvoted comments

@oliverandersencox, @Darapsas , @adhikarisandeep , @Rafcin It looks like this happens when in the data store enabled API.

When data store is enabled for an API, the conflict detection and resolution is set to AUTOMERGE. As documented here

Automerge

Automerge provides developers an easy way to configure a conflict resolution strategy without writing client-side logic to manually merge conflicts that were unable to be handled by other strategies. Automerge adheres to a strict rule set when merging data to resolve conflicts. The tenets of Automerge revolve around the underlying data type of the GraphQL field. They are as follows:

  • Conflict on a scalar field: GraphQL scalar or any field that is not a collection (i.e List, Set, Map). Reject the incoming value for the scalar field and select the value existing in the server.
  • Conflict on a list: GraphQL type and database type are lists. Concatenate the incoming list with the existing list in the server. The list values in the incoming mutation will be appended to the end of the list in the server. Duplicate values will be retained.
  • Conflict on a set: GraphQL type is a list and database type is a Set. Apply a set union using incoming the set and the existing set in the server. This adheres to the properties of a Set, meaning no duplicate entries.
  • When an incoming mutation adds a new field to the item, merge that on to the existing item.
  • Conflict on a map: When the underlying data type in the database is a Map (i.e. key-value document), apply the above rules as it parses and processes each property of the Map.

Automerge is designed to automatically detect, merge, and retry requests with an updated version, absolving the client from needing to manually merge any conflicting data.

If you want to update the JSON record, you can explictly pass the _version field in the input which ensures that the data is not automerged if the _version field in the input matches to that of one in your database

mutation UpdateItem {
  updateJsonTest(input: {id: "myid", json: "[{\"key6\": \"value6\"}]", _version: 5}) {
    id
    json
    _version
  }
}

Are there any updates on this? I am having the same issue and all aws packages are updated to newest versions. I think it is a little bit an overkill to delete the whole api and recreate it without conflict resolution.

I had to delete my entire api 2 days ago and redeployed using the exact same schema, and yes it was all working fine before this.

@SwaySway I take it back, it now seems that any array child of a parent model, when updated will duplicate the current values in the array. Any child on my event Model which is an sarray of types is doing it now. This is with parts of the code I havent even touched.

All network calls show the data being handed over is correct. For example if the current event.info field is [‘test’] and I run the update event method with { info: [‘testreplace’] } it will append it to the array even though im telling it to put a new array there!