Amplify-js: Datastore syncExpressions in a one to many relationship?

Created on 9 Jan 2021  路  11Comments  路  Source: aws-amplify/amplify-js

Which Category is your question related to?
Datastore

What AWS Services are you utilizing?
Appsync
Datastore

Provide additional details e.g. code snippets
Is it possible with Datastore syncExpressions in a one to many relationship if we sync the top model does the related items get synced too and nothing else?

Say for example

type Post @model {
  id: ID!
  comments: [Comment] @connection(keyName: "byPost", fields: ["id"])
}

type Comment @model
  @key(name: "byPost", fields: ["postID", "content"]) {
  id: ID!
  postID: ID!
  content: String!
}

Is it posible if we sync just Post model with Id then all it's related comments are synced and not all comments.

DataStore.configure({
  syncExpressions: [
    syncExpression(Post, () => {
      return (c) => c.id('eq', '123')
    }),
  ],
})
DataStore feature-request

Most helpful comment

@renebrandel Yeah I figured as much. The use case is fairly complex:

  • Organizations --> Projects --> Tasks
  • Users belong to N organizations, with privileges as admin or member
  • Organizations contain N projects
  • Projects contain N tasks
  • Users can be added to projects, with privileges as editor or viewer
  • Users can be assigned to tasks within projects
  • "Chat rooms" exist within Organizations with varying users
  • Ideally, real-time updates should be emitted for each model type, especially chats, tasks, projects
  • Users cannot, in any case, get data (UI or DB level) that they are not privileged to
  • Number of items can get very big, e.g. tasks, so replicating cloud store is not feasible
  • Tasks, for example, would belong many different projects from multiple organizations, so selective sync won't work AFAIK

So in a broad sense it's a mix of project/task management + whatsapp. Like @mir1198yusuf mentioned, if the whatsapp use case can be implemented at scale, you guys probably have a winning product. However, I can't wait months and months for something that (might) work. I would love to use DataStore, it's premise is amazing and the last thing I want to do is manage conflict resolution, but I don't believe it can do what I need.

With my use case above, do you think the AppSync SDK route will work (assuming DataStore route already doesn't)?

All 11 comments

This is a very much needed feature so we can only write syncExpression for top models and all related ones will be sync

@DevTGhosh Transferred to the JS repo as it is related more to the JS side and DataStore in general than CLI.

@DevTGhosh not at the moment. You would need to have a separate sync expression for the related items. E.g.,

DataStore.configure({
  syncExpressions: [
    syncExpression(Post, () => {
      return (c) => c.id('eq', '123')
    }),
    syncExpression(Comment, () => {
      return (c) => c.postID('eq', '123')
    }),
  ],
})

@iartemiev , I can see that you passed just one postId for Comment table.
suppose I want to fetch all posts that user is part of, then all comments for only each of this post .

How can I make such expression?

The condition for Comment syncExpression depends on array returned by Post syncExpression.

Basically what we are asking for is say we fetch Posts by tag but wanna get Comments of the posts we get which are related by id

type Post @model {
  id: ID!
  tag: String!
  comments: [Comment] @connection(keyName: "byPost", fields: ["id"])
}

type Comment @model
  @key(name: "byPost", fields: ["postID", "content"]) {
  id: ID!
  postID: ID!
  content: String!
}
DataStore.configure({
  syncExpressions: [
    syncExpression(Post, () => {
      return (c) => c.tag('eq', 'cooking')
    }),
    syncExpression(Comment, () => {
      // what would we write here so that we can get the id of the posts above and sync comments byPoistId
    }),
  ],
})

@iartemiev @renebrandel Out of curiosity at this point, what would the solution to the above be, if there is? Telling your sync engine to stop and start for many predicates is pretty odd.

If there's no current solution, it seems DataStore was not designed from the outset for many common application design patterns. Seems to be more useful for small-medium internal organization apps and demos, but not much else in the real world, which would generally be fine if the docs and AWS blog posts made that clear (which they don't). Please correct me if I'm wrong.

We鈥檝e recently launched sync expressions and are working on improvements now that we have more feedback from customers (like everyone on this thread). Over the next few months, we鈥檙e spending some time to rethink how relationships are handled. Look out for an RFC soon.

@renebrandel Great, thank your for the prompt response and update. In the meantime, is it safe to assume to that the AWS AppSync Client SDK would generally work for these more advanced scenarios with offline use, as indicated here: https://docs.amplify.aws/lib/graphqlapi/offline/q/platform/js?

I know there's never a 100% guarantee, but my concerns are it seems there's no offline support past apollo client ver 2.4.6 and I don't want to run into hidden issues down the road like I did with DataStore. Are you aware of any relatively complex implementations with subscriptions and offline use?

It'll depend on the scenarios itself. For offline-first applications, we do recommend DataStore as it provides many out-of-the-box benefits without manually configuring caching logic. AppSync Client SDK might be a better approach if you want to manually tweak those settings. You'll end up though manually managing conflict resolution logic etc. on top of it. If you can provide the use cases you're trying to tackle, then I can provide a recommendation.

@renebrandel -
You can see this use case https://github.com/aws-amplify/amplify-js/issues/7534#issuecomment-760412322

@iartemiev is already familiar with this issue. He has also tried few approaches and came to some conclusions which he has mentioned in that issue.

This use case covers most real-world scenarios. If you can consider this use case with priority , I think Datastore could become a successful product given the promises it makes. Multi-tenancy, dynamic selective syncing (not the kind in docs), etc are many issue which can be covered in this whatsapp clone use case. But make sure to fulfill all criteria as mentioned in the use case.

Just try to fit Datastore on this use case and you will understand the shortcomings of Datastore

@renebrandel Yeah I figured as much. The use case is fairly complex:

  • Organizations --> Projects --> Tasks
  • Users belong to N organizations, with privileges as admin or member
  • Organizations contain N projects
  • Projects contain N tasks
  • Users can be added to projects, with privileges as editor or viewer
  • Users can be assigned to tasks within projects
  • "Chat rooms" exist within Organizations with varying users
  • Ideally, real-time updates should be emitted for each model type, especially chats, tasks, projects
  • Users cannot, in any case, get data (UI or DB level) that they are not privileged to
  • Number of items can get very big, e.g. tasks, so replicating cloud store is not feasible
  • Tasks, for example, would belong many different projects from multiple organizations, so selective sync won't work AFAIK

So in a broad sense it's a mix of project/task management + whatsapp. Like @mir1198yusuf mentioned, if the whatsapp use case can be implemented at scale, you guys probably have a winning product. However, I can't wait months and months for something that (might) work. I would love to use DataStore, it's premise is amazing and the last thing I want to do is manage conflict resolution, but I don't believe it can do what I need.

With my use case above, do you think the AppSync SDK route will work (assuming DataStore route already doesn't)?

Was this page helpful?
0 / 5 - 0 ratings