mark_h
mark_h

Reputation: 5477

Apollo GraphQL query in service duplicates collection items?

I have the following method in a service within my Angular 6 app;

  public getPupilReport(): Observable<PupilReport> {
    return this.apollo.query<any>({
      query: gql`
            query query {
              pupilReports {
                new {
                  date
                  pupilReportTemplateId
                  pupilReportTemplate {
                    id
                    name
                    sortedPupilAttributeCollections {
                      sortOrder
                      pupilAttributeCollection {
                        id
                        name
                        sortedPupilAttributes {
                          sortOrder
                          pupilAttribute {
                            id
                            name
                            type
                          }
                        }
                      }
                    }
                  }
                }
              }
            }`,
    })
      .pipe(map(result => {
        var pupilReport = new PupilReport();
        if (result && result.data.pupilReports.new) {
          pupilReport = result.data.pupilReports.new;
        }
        return pupilReport;
      }));
  }

When I run the query above using GraphIQL I get the following data returned;

  "data": {
    "pupilReports": {
      "new": {
        "date": "0001-01-01",
        "pupilReportTemplateId": 0,
        "pupilReportTemplate": {
          "id": 99,
          "name": "KS3 Science",
          "sortedPupilAttributeCollections": [
            {
              "sortOrder": 1,
              "pupilAttributeCollection": {
                "id": 1,
                "name": "Attainment",
                "sortedPupilAttributes": [
                  {
                    "sortOrder": 1,
                    "pupilAttribute": {
                      "id": 1,
                      "name": "Physics",
                      "type": "Boolean"
                    }
                  },
                  {
                    "sortOrder": 2,
                    "pupilAttribute": {
                      "id": 1,
                      "name": "Biology",
                      "type": "Int32"
                    }
                  }
                ]
              }
            },
            {
              "sortOrder": 2,
              "pupilAttributeCollection": {
                "id": 1,
                "name": "Behaviour",
                "sortedPupilAttributes": [
                  {
                    "sortOrder": 1,
                    "pupilAttribute": {
                      "id": 3,
                      "name": "Attitude",
                      "type": "Int32"
                    }
                  },
                  {
                    "sortOrder": 2,
                    "pupilAttribute": {
                      "id": 4,
                      "name": "Effort",
                      "type": "Boolean"
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }

When the same query returns from the apollo query I get the following data (the pupilAttributeCollections and pupilAttributes all have the same data);

  "data": {
    "pupilReports": {
      "new": {
        "date": "0001-01-01",
        "pupilReportTemplateId": 0,
        "pupilReportTemplate": {
          "id": 99,
          "name": "KS3 Science",
          "sortedPupilAttributeCollections": [
            {
              "sortOrder": 1,
              "pupilAttributeCollection": {
                "id": 1,
                "name": "Attainment",
                "sortedPupilAttributes": [
                  {
                    "sortOrder": 1,
                    "pupilAttribute": {
                      "id": 1,
                      "name": "Physics",
                      "type": "Boolean"
                    }
                  },
                  {
                    "sortOrder": 2,
                    "pupilAttribute": {
                      "id": 1,
                      "name": "Physics",
                      "type": "Boolean"
                    }
                  }
                ]
              }
            },
            {
              "sortOrder": 2,
              "pupilAttributeCollection": {
                "id": 1,
                "name": "Attainment",
                "sortedPupilAttributes": [
                  {
                    "sortOrder": 1,
                    "pupilAttribute": {
                      "id": 1,
                      "name": "Physics",
                      "type": "Boolean"
                    }
                  },
                  {
                    "sortOrder": 1,
                    "pupilAttribute": {
                      "id": 1,
                      "name": "Physics",
                      "type": "Boolean"
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }

I am interpreting the second set of data based on inspecting the pupilReport object returned from the apollo query.

Can anyone offer any explanation as to why this might be? The data from the collection itself is hardcoded in the server so there's no way the second set of data is correct. I can only presume it has something to do with caching.

Upvotes: 2

Views: 3475

Answers (1)

mark_h
mark_h

Reputation: 5477

The cause of the duplicate data is the apollo caching system correctly doing its job.

Apollo identifies an object by its __typename and id (or _id) field. Due to an error in my hardcoded test data there are objects with duplicate IDs. Correcting my data so that all objects of the same type have unique IDs (as they should) fixed this issue.

If the id field is unavailable or the IDs are expected to be duplicated, a custom dataIdFromObject function can be provided to the InMemoryCache constructor to tell Apollo how to correctly normalize such objects.

See here for a better explanation

Upvotes: 4

Related Questions