Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"type mismatch error, expected type LIST" for querying a one-to-many relationship in AppSync

The schema:

type User {
    id: ID!
    createdCurricula: [Curriculum]
}

type Curriculum {
    id: ID!
    title: String!
    creator: User!
}

The resolver to query all curricula of a given user:

    {
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        ## Provide a query expression. **
        "expression": "userId = :userId",
        "expressionValues" : {
            ":userId" : {
                "S" : "${context.source.id}"
            }
        }
    },
    "index": "userIdIndex",
    "limit": #if(${context.arguments.limit}) ${context.arguments.limit} #else 20 #end,
    "nextToken": #if(${context.arguments.nextToken}) "${context.arguments.nextToken}" #else null #end
    }

The response map:

{
"items": $util.toJson($context.result.items),
"nextToken": #if(${context.result.nextToken}) "${context.result.nextToken}" #else null #end
}

The query:

query {
  getUser(id: "0b6af629-6009-4f4d-a52f-67aef7b42f43") {
    id
    createdCurricula {
      title
    }
  }
}

The error:

{
  "data": {
    "getUser": {
      "id": "0b6af629-6009-4f4d-a52f-67aef7b42f43",
      "createdCurricula": null
    }
  },
  "errors": [
    {
      "path": [
        "getUser",
        "createdCurricula"
      ],
      "locations": null,
      "message": "Can't resolve value (/getUser/createdCurricula) : type mismatch error, expected type LIST"
    }
  ]
}

The CurriculumTable has a global secondary index titled userIdIndex, which has userId as the partition key.

If I change the response map to this:

$util.toJson($context.result.items)

The output is the following:

{
  "data": {
    "getUser": {
      "id": "0b6af629-6009-4f4d-a52f-67aef7b42f43",
      "createdCurricula": null
    }
  },
  "errors": [
    {
      "path": [
        "getUser",
        "createdCurricula"
      ],
      "errorType": "MappingTemplate",
      "locations": [
        {
          "line": 4,
          "column": 5
        }
      ],
      "message": "Unable to convert \n{\n    [{\"id\":\"87897987\",\"title\":\"Test Curriculum\",\"userId\":\"0b6af629-6009-4f4d-a52f-67aef7b42f43\"}],\n} to class java.lang.Object."
    }
  ]
}

If I take that string and run it through a console.log in my frontend app, I get:

{
[{"id":"2","userId":"0b6af629-6009-4f4d-a52f-67aef7b42f43"},{"id":"1","userId":"0b6af629-6009-4f4d-a52f-67aef7b42f43"}]
}

That's clearly an object. How do I make it... not an object, so that AppSync properly reads it as a list?

SOLUTION

My response map had a set of curly braces around it. I'm pretty sure that was placed there in the generator by Amazon. Removing them fixed it.

like image 488
Zak Singh Avatar asked Jan 28 '18 03:01

Zak Singh


2 Answers

I think I'm not seeing the complete view of your schema, I was expecting something like:

schema {
   query: Query
}

Where Query is RootQuery, in fact you didn't share us your Query definition. Assuming you have the right Query definition. The main problem is in your response template.

> "items": $util.toJson($context.result.items)

This means that you are passing a collection named: *"items"* to Graphql query engine. And you are referring this collection as "createdCurricula". So solve this issue your response-mapping-template is the right place to fix. How? just replace the above line with the following.

"createdCurricula": $util.toJson($context.result.items),

Please the main thing to note here is, the mapping template is a bridge between your datasources and qraphql, feel free to make any computation, or name mapping but don't forget that object names in that response json are the one should match in schema/query definition.

Thanks.

Musema

like image 173
Musema Avatar answered Oct 23 '22 21:10

Musema


change to result type to $util.toJson($ctx.result.data.posts)

like image 1
Naresh Choudhary Avatar answered Oct 23 '22 23:10

Naresh Choudhary