diff --git a/src/fragments/lib/datastore/js/data-access/delete-snippet.mdx b/src/fragments/lib/datastore/js/data-access/delete-snippet.mdx index a66b1665828..a7b8b06c6ff 100644 --- a/src/fragments/lib/datastore/js/data-access/delete-snippet.mdx +++ b/src/fragments/lib/datastore/js/data-access/delete-snippet.mdx @@ -6,14 +6,14 @@ DataStore.delete(todelete); You can also pass predicate operators to delete multiple items. For example, the following will delete all draft posts: ```js -await DataStore.delete(Post, (post) => post.status('eq', PostStatus.INACTIVE)); +await DataStore.delete(Post, (post) => post.status.eq(PostStatus.INACTIVE)); ``` Additionally, you can perform a conditional delete. For instance, only delete **if** a post is in draft status by passing in an instance of a model: ```js const todelete = await DataStore.query(Post, '123'); -DataStore.delete(todelete, (post) => post.status('eq', PostStatus.INACTIVE)); +DataStore.delete(todelete, (post) => post.status.eq(PostStatus.INACTIVE)); ``` Also, to delete all items for a model you can use `Predicates.ALL`: diff --git a/src/fragments/lib/datastore/js/data-access/observe-update-snippet.mdx b/src/fragments/lib/datastore/js/data-access/observe-update-snippet.mdx index b6817e0f128..dfe018ba27c 100644 --- a/src/fragments/lib/datastore/js/data-access/observe-update-snippet.mdx +++ b/src/fragments/lib/datastore/js/data-access/observe-update-snippet.mdx @@ -12,7 +12,7 @@ function App() { * This keeps `todo` fresh. */ const sub = DataStore.observeQuery(Post, (c) => - c.id("eq", "e4dd1dc5-e85c-4566-8aaa-54a801396456") + c.id.eq("e4dd1dc5-e85c-4566-8aaa-54a801396456") ).subscribe(({ items }) => { setPost(items[0]); }); diff --git a/src/fragments/lib/datastore/js/data-access/query-predicate-multiple-snippet.mdx b/src/fragments/lib/datastore/js/data-access/query-predicate-multiple-snippet.mdx index bc26acf3486..ff3a50b0482 100644 --- a/src/fragments/lib/datastore/js/data-access/query-predicate-multiple-snippet.mdx +++ b/src/fragments/lib/datastore/js/data-access/query-predicate-multiple-snippet.mdx @@ -1,7 +1,8 @@ -When using multiple conditions, there is an implicit `and` defined to mirror the [GraphQL Transformer condition statements](/cli/graphql/data-modeling). For example with multiple conditions: +When using multiple conditions, you can wrap the predicates with the `and` operator. For example with multiple conditions: ```js -const posts = await DataStore.query(Post, (c) => - c.rating('gt', 4).status('eq', PostStatus.ACTIVE) -); +const posts = await DataStore.query(Post, (c) => c.and(c => [ + c.rating.gt(4), + c.status.eq(PostStatus.ACTIVE) +])); ``` diff --git a/src/fragments/lib/datastore/js/data-access/query-predicate-or-snippet.mdx b/src/fragments/lib/datastore/js/data-access/query-predicate-or-snippet.mdx index 9db1139f962..1a11a675c64 100644 --- a/src/fragments/lib/datastore/js/data-access/query-predicate-or-snippet.mdx +++ b/src/fragments/lib/datastore/js/data-access/query-predicate-or-snippet.mdx @@ -2,6 +2,8 @@ If you wanted this to be an `or` statement you would wrap your combined predicat ```js const posts = await DataStore.query(Post, (c) => - c.or((c) => c.rating('gt', 4).status('eq', PostStatus.ACTIVE)) -); + c.or(c => [ + c.rating.gt(4), + c.status.eq(PostStatus.ACTIVE) + ])); ``` diff --git a/src/fragments/lib/datastore/js/data-access/query-predicate-snippet.mdx b/src/fragments/lib/datastore/js/data-access/query-predicate-snippet.mdx index e91f7e5f75e..0ce211b0f65 100644 --- a/src/fragments/lib/datastore/js/data-access/query-predicate-snippet.mdx +++ b/src/fragments/lib/datastore/js/data-access/query-predicate-snippet.mdx @@ -1,3 +1,3 @@ ```js -const posts = await DataStore.query(Post, c => c.rating("gt", 4)); +const posts = await DataStore.query(Post, c => c.rating.gt(4)); ``` diff --git a/src/fragments/lib/datastore/js/examples-react-native.mdx b/src/fragments/lib/datastore/js/examples-react-native.mdx index 3def9517ef5..1b2d38aa01c 100644 --- a/src/fragments/lib/datastore/js/examples-react-native.mdx +++ b/src/fragments/lib/datastore/js/examples-react-native.mdx @@ -68,7 +68,7 @@ class App extends Component { } onQuery = async () => { - const posts = await DataStore.query(Post, (c) => c.rating('gt', 2)); + const posts = await DataStore.query(Post, (c) => c.rating.gt(2)); console.log('QUERY_POSTS_RESULT', posts); const comments = await DataStore.query(Comment); this.setState({ posts }); diff --git a/src/fragments/lib/datastore/js/examples.mdx b/src/fragments/lib/datastore/js/examples.mdx index c8e1ae2ae5c..22d19b9b059 100644 --- a/src/fragments/lib/datastore/js/examples.mdx +++ b/src/fragments/lib/datastore/js/examples.mdx @@ -34,7 +34,7 @@ function onDeleteAll() { } async function onQuery() { - const posts = await DataStore.query(Post, (c) => c.rating("gt", 4)); + const posts = await DataStore.query(Post, (c) => c.rating.gt(4)); console.log(posts); } @@ -108,7 +108,7 @@ export class AppComponent implements OnInit, OnDestroy { } public async loadPosts() { - let posts = await DataStore.query(Post, (c) => c.rating("gt", 4)); + let posts = await DataStore.query(Post, (c) => c.rating.gt(4)); console.log(posts); } @@ -169,7 +169,7 @@ export default { }, methods: { async onQuery() { - let posts = await DataStore.query(Post, (c) => c.rating("gt", 4)); + let posts = await DataStore.query(Post, (c) => c.rating.gt(4)); console.log(posts); }, onCreate() { diff --git a/src/fragments/lib/datastore/js/real-time/observe-query-snippet.mdx b/src/fragments/lib/datastore/js/real-time/observe-query-snippet.mdx index f54f16e13ed..f9718d07401 100644 --- a/src/fragments/lib/datastore/js/real-time/observe-query-snippet.mdx +++ b/src/fragments/lib/datastore/js/real-time/observe-query-snippet.mdx @@ -1,8 +1,10 @@ ```js const subscription = DataStore.observeQuery( Post, - p => p.title("beginsWith", "post").rating("gt", 10), - { + p => p.and(p => [ + p.title.beginsWith("post"), + p.rating.gt(10) + ]), { sort: s => s.rating(SortDirection.ASCENDING) } ).subscribe(snapshot => { diff --git a/src/fragments/lib/datastore/js/relational/query-many-snippet.mdx b/src/fragments/lib/datastore/js/relational/query-many-snippet.mdx index 09e432b123b..772528b4aea 100644 --- a/src/fragments/lib/datastore/js/relational/query-many-snippet.mdx +++ b/src/fragments/lib/datastore/js/relational/query-many-snippet.mdx @@ -1,48 +1,48 @@ -These many-to-many relationship models can be queried directly to return all models in the relationship: +### Create + +In order to save a many-to-many relationship, create both model instance first and then save them to a new join model instance. ```js -// All post editor relationships -const results = await DataStore.query(PostEditor); +const post = await DataStore.save(new Post({ + title: 'Amplify Weekly' + rating: 10, + status: PostStatus.ACTIVE, +})) + +const user = await DataStore.save(new User({ + username: 'rene' +})) + +const postEditor = await DataStore.save(new PostEditor({ + post: post, + user: user +})) ``` -This will return an array of `PostEditor`s with `Post` and `Editor` model instances attached. For example, without metadata, `results` from above would look like this: - -```json -[ - { - "id": "4b66cee3-1436-4d53-910f-7cfe0d955cd8", - "post": { - "id": "d2a96183-938f-4469-9873-944336fb9d9d", - "title": "My first post" - }, - "editor": { - "id": "2cbfdd83-8353-4b0e-ae63-8f7d004c728f", - "username": "Nadia" - } - } -] +Here we've first created a new `Post` instance and a new `User` instance. Then, saved those instances to a new instance of our join model `PostEditor`. + +### Query + +To query many-to-many relationships, use a nested predicate to filter the target model by the source model's id: + +```js +const editors = await DataStore.query(User, u => u.posts.post.id.eq(post.id)) ``` -This model instance contains both related models. Use `filter()` or `map()` to retrieve the related model instances: +### Delete + +Deleting the join model instance will not delete any source model instances. ```js -// All posts for a given editor -const postsByEditor = (await DataStore.query(PostEditor)).filter( - pe => pe.editor.id === editor.id -).map(pe => pe.post); - -// All editors on a given post -const editorsByPost = (await DataStore.query(PostEditor)).filter( - pe => pe.post.id === post.id -).map(pe => pe.editor); - -// All editors of posts where title contains "first" -const editorsOfFirstPosts = (await DataStore.query(PostEditor)).filter( - pe => pe.post.title.includes("first") -).map(pe => pe.editor); - -// All editors of posts where title is long -const editorsWithLongTitles = (await DataStore.query(PostEditor)).filter( - pd => pe.post.title.length > 20 -).map(pe => pe.editor); -``` \ No newline at end of file +await DataStore.delete(toBeDeletedPostEditor) +``` + +Both the `Post` and the `User` instances will not be deleted. Only the join model instances containing the link between a `Post` and a `User`. + +Deleting a source model instance will also delete the join model instances containing the source model instance. + +```js +await DataStore.delete(toBeDeletedUser) +``` +The `toBeDeletedUser` User instance and all `PostEditor` instances where `user` is linked to `toBeDeletedUser` will be deleted. + diff --git a/src/fragments/lib/datastore/js/relational/query-snippet.mdx b/src/fragments/lib/datastore/js/relational/query-snippet.mdx index 1be1e00c03d..a3169cc8315 100644 --- a/src/fragments/lib/datastore/js/relational/query-snippet.mdx +++ b/src/fragments/lib/datastore/js/relational/query-snippet.mdx @@ -1,10 +1,20 @@ +You can query related models in three ways: + +- Option 1: use the `toArray()` function to lazy load related comments ```js -const comments = (await DataStore.query(Comment)).filter(c => c.postID === "123"); +const post = await DataStore.query(Post, "YOUR_POST_ID") +const comments = await post.comments.toArray() ``` -Alternatively: - +- Option 2: use async iterators to lazy load related comments ```js -const post = await DataStore.query(Post, "123"); -const comments = (await DataStore.query(Comment)).filter(c => c.postID === post.id); +const post = await DataStore.query(Post, "YOUR_POST_ID") +for await (const comment of post.comments) { + console.log(comment) +} ``` + +- Option 3: use nested query predicates with the `Comment` model +```js +const comments = await DataStore.query(Comment, c => c.post.id.eq('YOUR_POST_ID')); +``` \ No newline at end of file diff --git a/src/fragments/lib/datastore/js/relational/save-snippet.mdx b/src/fragments/lib/datastore/js/relational/save-snippet.mdx index e1fff0c5b12..39e73c34380 100644 --- a/src/fragments/lib/datastore/js/relational/save-snippet.mdx +++ b/src/fragments/lib/datastore/js/relational/save-snippet.mdx @@ -10,7 +10,7 @@ const post = await DataStore.save( await DataStore.save( new Comment({ content: "Loving Amplify DataStore!", - postID: post.id + post: post }) ); ``` diff --git a/src/fragments/lib/datastore/js/sync/20-savePredicate.mdx b/src/fragments/lib/datastore/js/sync/20-savePredicate.mdx index 3cf97effbb6..6d1677524f7 100644 --- a/src/fragments/lib/datastore/js/sync/20-savePredicate.mdx +++ b/src/fragments/lib/datastore/js/sync/20-savePredicate.mdx @@ -5,6 +5,6 @@ await DataStore.save( rating: 10, status: PostStatus.INACTIVE }), - (p) => p.title('beginsWith', '[Amplify]') + (p) => p.title.beginsWith('[Amplify]') ); ``` diff --git a/src/fragments/lib/datastore/js/sync/30-savePredicateComparison.mdx b/src/fragments/lib/datastore/js/sync/30-savePredicateComparison.mdx index ccb945c1c8e..9ee9c2a3af6 100644 --- a/src/fragments/lib/datastore/js/sync/30-savePredicateComparison.mdx +++ b/src/fragments/lib/datastore/js/sync/30-savePredicateComparison.mdx @@ -11,6 +11,6 @@ await DataStore.save( rating: 10, status: PostStatus.INACTIVE }), - (p) => p.title('beginsWith', '[Amplify]') + (p) => p.title.beginsWith('[Amplify]') ); ``` diff --git a/src/fragments/lib/datastore/js/sync/50-selectiveSync.mdx b/src/fragments/lib/datastore/js/sync/50-selectiveSync.mdx index 038bbac3bc5..0b00e49a29e 100644 --- a/src/fragments/lib/datastore/js/sync/50-selectiveSync.mdx +++ b/src/fragments/lib/datastore/js/sync/50-selectiveSync.mdx @@ -14,10 +14,10 @@ import { Post, Comment } from './models'; DataStore.configure({ syncExpressions: [ syncExpression(Post, () => { - return post => post.rating('gt', 5); + return post => post.rating.gt(5); }), syncExpression(Comment, () => { - return comment => comment.status('eq', 'active'); + return comment => comment.status.eq('active'); }), ] }); @@ -42,7 +42,7 @@ let rating = 5; DataStore.configure({ syncExpressions: [ syncExpression(Post, () => { - return post => post.rating('gt', rating)); + return post => post.rating.gt(rating); }) ] }); @@ -84,7 +84,7 @@ DataStore.configure({ syncExpressions: [ syncExpression(Post, () => { if (rating) { - return post => post.rating('gt', rating)); + return post => post.rating.gt(rating); } return Predicates.ALL; @@ -105,7 +105,7 @@ DataStore.configure({ syncExpressions: [ syncExpression(Post, async () => { const ratingValue = await getRatingValue(); - return post => post.rating('gt', ratingValue); + return post => post.rating.gt(ratingValue); }) ] }); @@ -117,7 +117,7 @@ If you don't need to add any logic to your `syncExpression`, you can use the fol ```js DataStore.configure({ syncExpressions: [ - syncExpression(Post, post => post.rating('gt', 5)) + syncExpression(Post, post => post.rating.gt(5)) ] }); ``` @@ -144,7 +144,7 @@ DataStore.configure({ syncExpressions: [ syncExpression(User, () => { const lastName = await getLastNameForSync(); - return user => user.lastName('eq', lastName) + return user => user.lastName.eq(lastName) }) ] }); @@ -155,7 +155,10 @@ DataStore.configure({ syncExpressions: [ syncExpression(User, () => { const lastName = await getLastNameForSync(); - return user => user.lastName('eq', lastName).createdAt('gt', '2020-10-10') + return user => user.and(user => [ + user.lastName.eq(lastName), + user.createdAt.gt('2020-10-10') + ]) }) ] }); @@ -163,8 +166,8 @@ DataStore.configure({ To construct a query expression, return a predicate with the primary key of the GSI. You can only use the `eq` operator with this predicate. -For the schema defined above `user => user.lastName('eq', 'Bobby')` is a valid query expression. +For the schema defined above `user => user.lastName.eq('Bobby')` is a valid query expression. -Optionally, you can also chain the sort key to this expression, using any of the following operators: `eq | ne | le | lt | ge | gt | beginsWith | between`. +Optionally, you can also add the sort key to this expression with an `and` operator and any of the following operators: `eq | ne | le | lt | ge | gt | beginsWith | between`. -E.g., `user => user.lastName('eq', 'Bobby').createdAt('gt', '2020-10-10')`. +E.g., `user => user.and(user => [user.lastName.eq('Bobby'), user.createdAt.gt('2020-10-10')])`. diff --git a/src/fragments/lib/datastore/native_common/relational.mdx b/src/fragments/lib/datastore/native_common/relational.mdx index 660620fb03c..75ce1c77cd3 100644 --- a/src/fragments/lib/datastore/native_common/relational.mdx +++ b/src/fragments/lib/datastore/native_common/relational.mdx @@ -101,7 +101,7 @@ import flutter15 from "/src/fragments/lib/datastore/flutter/relational/delete-sn However, in a many-to-many relationship the children are not removed and you must explicitly delete them. -### Many-to-many +## Many-to-many relationships For many-to-many relationships, you can use the `@manyToMany` directive and specify a `relationName`. Under the hood, Amplify creates a join table and a one-to-many relationship from both models.