aws-amplify/amplify-js

Datastore - Observe query results in real-time with @hasOne relation doesn't add nested data after first sync

sebboe opened this issue · 11 comments

Before opening, please confirm:

  • I have installed the latest version of the Amplify CLI (see above), and confirmed that the issue still persists.
  • I have searched for duplicate or closed issues.
  • I have read the guide for submitting bug reports.
  • I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
  • I have removed any sensitive information from my code snippets and submission.

How did you install the Amplify CLI?

npm

If applicable, what version of Node.js are you using?

No response

Amplify CLI Version

7.6.22

What operating system are you using?

Mac

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

No manual changes made

Amplify Categories

api

Amplify Commands

Not applicable

Describe the bug

I'm facing an issue while observing objects with "@hasone" relationship. When adding a new object, the observer returns only the main object, without the relation field. After one refresh/moving to another component and coming back, the nested object appears as part of the main object.

According to the doc:

observeQuery(...) returns an initial data set, similar to query(...), and also automatically subscribes to subsequent changes to the query.

Expected behavior

I would like to directly return the nested object.

Reproduction steps

  1. Link two models with "@hasone"
  2. Add object with relation
  3. Observe objects:
    this.flightList = DataStore.observeQuery(Flight).subscribe(snapshot => {
      const { items, isSynced } = snapshot;
      console.log(`[Snapshot] item count: ${items.length}, isSynced: ${isSynced}`);
      console.log(items);
      this.flights = items;
    });

GraphQL schema(s)

# Put schemas below this line
type Flight @model {
  id: ID!
  pilot: String!
  airplane: Aircraft @hasOne(fields: ["airplaneId"])
  airplaneId: ID
}

type Aircraft @model {
  id: ID!
  registration: String!
  category: String
  lastIndex: String
  specs: AircraftSpecs
}

type AircraftSpecs {
  passenger:Boolean
  fuel:String
}

Log output

# Object returned right after saving it:
{
    "id": "5a91ab15-0866-4919-9703-3083018cdeab",
    "pilot": "Sébastien",
    "airplaneId": "3e154d19-af70-47d2-9d66-829fce65b93a",
    "_version": 1,
    "_lastChangedAt": 1646679807385,
    "_deleted": null
}
# Object returned after refresh
{
    "id": "5a91ab15-0866-4919-9703-3083018cdeab",
    "pilot": "Sébastien",
    "airplaneId": "3e154d19-af70-47d2-9d66-829fce65b93a",
    "_version": 1,
    "_lastChangedAt": 1646679807385,
    "_deleted": null,
    "airplane": {
        "id": "3e154d19-af70-47d2-9d66-829fce65b93a",
        "registration": "AV-ION",
        "category": "Airplane",
        "lastIndex": "22299:99",
        "createdAt": "2022-03-06T23:30:51.363Z",
        "updatedAt": "2022-03-07T19:03:27.671Z",
        "specs": {
            "passenger": true,
            "fuel": "AVGAS"
        },
        "_version": 8,
        "_lastChangedAt": 1646679807692,
        "_deleted": null
    }
}

Additional information

No response

Hey @sebboe 👋 thanks for raising this! I'm going to transfer this over to the amplify-js repo for better support as this appears to be an issue with DataStore

As a workaround, instead of using data returned by the subscription, I call a classic DataStore.query when new data are emitted.

    this.flightList = DataStore.observeQuery(Flight).subscribe(snapshot => {
      //const { items, isSynced } = snapshot;
      //console.log(`[Snapshot] item count: ${items.length}, isSynced: ${isSynced}`);
      this.refreshData().then(flights => {
        this.flights = flights;
        console.log(this.flights);
      })
    });
  }

  async refreshData(){
    this.flights = await DataStore.query(Flight);
    return this.flights
  }

I also see this issue and the same problem arises after updating the model. The re-query workaround addresses both issues.

I am also have this issue, I'll try the re-query workaround.

@sebboe This should be fixed. Are you still seeing this problem on the latest version of amplify?

I am still not receiving nested objects from the observe part of observeQuery and my datastore version is 3.12.6 (most up to date)

May be related to #10211

One thing about updating relationships as being different from adding a new one. In the above example, if postID is null then updating the Comments document only requires setting postID. If postID is already pointing to post "A", then updating just postID to the ID of post "B" fails. Update (and delete - set posID=null) of an existing relationship requires also setting post to the "B" post model.

Why is setting the model reference field required? post is a calculated field.

I have also noticed that one can set postID to anything if postID was null previously. If postID is a value that is not the ID of a Post document, then no error is generated on the update. querying/observing will obviously not return a Post model in the post field in this case.

I'm not able to reproduce this. It may have been incidentally fixed with the lazy loading change. Please comment if you are still experiencing this issue.