Jamie Hutber
Jamie Hutber

Reputation: 28126

GraphQL AWS AMplify @connection not bringing in connected data

I would like to have in the League tables all of the seasons and divisions as you can see with data > seasons. I have set it up as I believe would work using @connection.

So the question is, how would I have to change my division schema so that divisions are included in the League.

I have spent a good time reading over @connections & @key and understand that when using the key a hash is created with the ID that I have given them. But I do not understand enough having read the connections documentation multiple times as to why this wouldn't work.

I would love to understand this better, so i am giving all I can to try to develop an understanding!

n.b I believe it is worth mentioning also, that each time I change my schema and the amplify mock rebuilds the hash keys, they get added. I wonder if this has some impact? Should I be cleaning the SQLite completely with each schema change when keys are involved? enter image description here

League Schema

type League @model
{
  id: ID!
  name: String!
  faId: ID!
  logo: String
  seasons: [Season] @connection(keyName: "bySeason", fields: ["id"])
  division: [Division] @connection(keyName: "byDivision", fields: ["id"])
}

Seasons Schama

type Season @model @key(name: "bySeason", fields: ["leagueID"])
{
  id: ID!
  name: String!
  faId: ID!
  yearStart: AWSDate
  yearEnd: AWSDate
  leagueID: ID!
  league: League! @connection(fields: ["leagueID"])
  division: [Division] @connection(keyName: "byDivision", fields: ["id"])
}

Division Schema

type Division @model
@key(name: "byDivisionFromSeason", fields: ["leagueID" "name"])
@key(name: "byDivision", fields: ["seasonID", "leagueID"])
{
  id: ID!
  name: String!
  faId: ID!
  divisionSeasonFaId: String
  leagueID: ID!
  seasonID: ID!
  league: League! @connection(fields: ["leagueID"])
  season: Season! @connection(fields: ["seasonID"])
  teams: [TeamConnection] @connection(keyName: "byTeamDivision", fields: ["id"])
  games: [Game] @connection(keyName: "byGameForDivision", fields: ["id"])
  ageInput: String!
  level: Int!
}

Queries

  listLeagues {
    items {
      name
      division {
        items {
          name
        }
      }
      seasons {
        items {
          name
          division {
            items {
              name
            }
          }
        }
      }
    }
  }

Data

I have shown here that the structure is correct as the Seasons included in the League have the Divisions as expected

{
  "data": {
    "listLeagues": {
      "items": [
        {
          "name": "Southern Amateur League",
          "division": {
            "items": []
          },
          "seasons": {
            "items": [
              {
                "name": "2020-21",
                "division": {
                  "items": [
                    {
                      "name": "Junior Section Division 5B South"
                    },
                    {
                      "name": "Junior Section Division 4 South"
                    },
                    {
                      "name": "Intermediate Division 3"
                    },
                  ]
                }
              },
              {
                "name": "2019-20",
                "division": {
                  "items": []
                }
              },
            ]
          }
        }
      ]
    }
  }
}

Edit

Since reducing just the keys on division to seasonID and leagueID on each key, when clearing the data it appears to throw an unusual error. I had believed that return null on a @connection was perfectly valid?

enter image description here

Upvotes: 8

Views: 1096

Answers (2)

jccampanero
jccampanero

Reputation: 53461

Maybe this should be more a comment than an actual answer, but I need to describe the schema, I will delete it later if you consider it appropriate.

Jamie, just for testing, can you please try the following schema? It is basically the same schema proposed by Nader, just removing the field name from the keys on Division:

type League @model
{
  id: ID!
  name: String!
  faId: ID!
  logo: String
  seasons: [Season] @connection(keyName: "bySeason", fields: ["id"])
  division: [Division] @connection(keyName: "byDivision", fields: ["id"])
}

type Season @model @key(name: "bySeason", fields: ["leagueID"])
{
  id: ID!
  name: String!
  faId: ID!
  yearStart: AWSDate
  yearEnd: AWSDate
  leagueID: ID!
  league: League! @connection(fields: ["leagueID"])
  division: [Division] @connection(keyName: "byDivisionFromSeason", fields: ["id"])
}

type Division @model
@key(name: "byDivisionFromSeason", fields: ["seasonID", "leagueID"])
@key(name: "byDivision", fields: ["leagueID", "seasonID"])
{
  id: ID!
  name: String!
  faId: ID!
  divisionSeasonFaId: String
  leagueID: ID!
  seasonID: ID!
  league: League! @connection(fields: ["leagueID"])
  season: Season! @connection(fields: ["seasonID"])
  teams: [TeamConnection] @connection(keyName: "byTeamDivision", fields: ["id"])
  games: [Game] @connection(keyName: "byGameForDivision", fields: ["id"])
  ageInput: String!
  level: Int!
}

I think the error you obtained, i.e.:

"errors": [ { "message": "Query condition missed key schema element", "errorType": "DynamoDB:ValidationException", "data": null, "errorInfo": null, "path": [ "listLeagues", "items", 1, "division" ], "locations": [ { "line": 10, "column": 9, "sourceName": "GraphQL request" } ] }

can be motivated by running a query using the condition name.

Upvotes: 2

Nader Dabit
Nader Dabit

Reputation: 53711

Because you are setting two different types of query patterns on the division (one from the League using the league ID and one from the Season using the season ID), you should create two indexes. Try something like this:

type League @model {
  id: ID!
  name: String!
  faId: ID!
  logo: String
  seasons: [Season] @connection(keyName: "bySeason", fields: ["id"])
  division: [Division] @connection(keyName: "byDivision", fields: ["id"])
}

type Season @model @key(name: "bySeason", fields: ["leagueID"]) {
  id: ID!
  name: String!
  faId: ID!
  yearStart: AWSDate
  yearEnd: AWSDate
  leagueID: ID!
  league: League! @connection(fields: ["leagueID"])
  division: [Division] @connection(keyName: "byDivisionFromSeason", fields: ["id"])
}

type Division @model
  @key(name: "byDivisionFromSeason", fields: ["seasonID", "leagueID", "name"])
  @key(name: "byDivision", fields: ["leagueID", "seasonID", "name"]) {
  id: ID!
  name: String!
  faId: ID!
  leagueID: ID!
  seasonID: ID!
  league: League! @connection(fields: ["leagueID"])
  season: Season! @connection(fields: ["seasonID"])
  ageInput: String!
  level: Int!
}

Upvotes: 1

Related Questions