You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/pages/[platform]/build-a-backend/graphqlapi/relational-models/index.mdx
+234-6Lines changed: 234 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,10 @@ export const meta = {
4
4
title: 'Relational models',
5
5
description:
6
6
'Learn more about how API (GraphQL) handles relationships between Models, such as "has one", "has many", "belongs to".',
7
-
platforms: ['android']
7
+
platforms: [
8
+
'android',
9
+
'swift'
10
+
]
8
11
};
9
12
10
13
exportconst getStaticPaths =async () => {
@@ -20,7 +23,7 @@ export function getStaticProps(context) {
20
23
};
21
24
}
22
25
23
-
<InlineFilterfilters={["android"]}>
26
+
<InlineFilterfilters={["android", "swift"]}>
24
27
25
28
API (GraphQL) has the capability to handle relationships between Models, such as _has one_, _has many_, and _belongs to_. In Amplify GraphQL APIs, this is done with the `@hasOne`, `@hasMany` and `@belongsTo` directives as defined in the [GraphQL data modeling documentation](/[platform]/build-a-backend/graphqlapi/data-modeling/).
26
29
@@ -44,6 +47,20 @@ If you already have relational models in your project, you must re-run `amplify
44
47
45
48
</InlineFilter>
46
49
50
+
<InlineFilterfilters={["swift"]}>
51
+
52
+
- Amplify CLI v10.8.0
53
+
- Amplify Library for Swift v2.4.0
54
+
- This guide uses updated model types generated by the Amplify CLI. To follow this guide, locate `"generatemodelsforlazyloadandcustomselectionset"` in `{project-directory}/amplify/cli.json` and set the value to `true`.
55
+
56
+
<Callout>
57
+
58
+
If you already have relational models in your project, you must re-run `amplify codegen models` after updating the feature flag. After the models have been updated, breaking changes will need to be addressed because some relationships have changed to `async`. Follow the rest of the guide on this page information on how to use the new lazy supported models.
59
+
60
+
</Callout>
61
+
62
+
</InlineFilter>
63
+
47
64
## Create a GraphQL schema with relationships between models
48
65
49
66
For the following example, let's add a Post and Comment model to the [schema](/[platform]/build-a-backend/graphqlapi/set-up-graphql-api/#creating-your-first-api-and-database-table):
@@ -157,6 +174,37 @@ try {
157
174
158
175
</InlineFilter>
159
176
177
+
<InlineFilterfilters={["swift"]}>
178
+
179
+
<Block>
180
+
181
+
```swift
182
+
do {
183
+
let post =Post(title: "My post with comments",
184
+
rating: 10)
185
+
let comment =Comment(content: "Loving Amplify API!",
186
+
post: post) // Directly pass in the post instance
187
+
188
+
let createPostResult =tryawait Amplify.API.mutate(request: .create(post))
189
+
guardcase .success = createPostResult else {
190
+
print("API response: \(createPostResult)")
191
+
return
192
+
}
193
+
print("Post created.")
194
+
let createCommentResult =tryawait Amplify.API.mutate(request: .create(comment))
195
+
guardcase .success = createCommentResult else {
196
+
print("API response: \(createCommentResult)")
197
+
return
198
+
}
199
+
print("Comment created.")
200
+
} catch {
201
+
print("Create post or comment failed", error)
202
+
}
203
+
```
204
+
205
+
</Block>
206
+
</InlineFilter>
207
+
160
208
## Querying relationships
161
209
162
210
This example demonstrates an initial load of a Post with a subsequent fetch to load a page of comments for the post.
@@ -439,6 +487,32 @@ suspend fun getCommentsForPost(post: Post) {
439
487
440
488
</InlineFilter>
441
489
490
+
<InlineFilter filters={["swift"]}>
491
+
492
+
<Block>
493
+
494
+
```swift
495
+
do {
496
+
let queryPostResult =try await Amplify.API.query(request: .get(Post.self, byIdentifier:"123"))
497
+
guard case .success(let queriedPostOptional) = queryPostResult,
498
+
let queriedPost = queriedPostOptional,
499
+
let comments = queriedPost.comments else {
500
+
print("API response: \(queryPostResult)")
501
+
return
502
+
}
503
+
try await comments.fetch()
504
+
print("Fetched \(comments.count) comments")
505
+
} catch {
506
+
print("Failed to query post or fetch comments", error)
507
+
}
508
+
```
509
+
510
+
</Block>
511
+
512
+
Always call `fetch()` to load or retrieve the comments. If the comments were loaded as part of the query, it will return immediately. See [CustomizingQueryDepth](#customizing-query-depth-with-custom-selection-sets) to learn how to eagerly load connected relationships.
513
+
514
+
</InlineFilter>
515
+
442
516
## Deleting relationships
443
517
444
518
When you delete a parent object in a one-to-many relationship, the children will not be removed. Delete the children before deleting the parent to prevent orphaned data.
@@ -502,6 +576,33 @@ try {
502
576
503
577
</InlineFilter>
504
578
579
+
<InlineFilter filters={["swift"]}>
580
+
581
+
<Block>
582
+
583
+
```swift
584
+
do {
585
+
let deleteCommentResult =try await Amplify.API.mutate(request: .delete(comment))
586
+
guard case .success = deleteCommentResult else {
587
+
print("API response: \(deleteCommentResult)")
588
+
return
589
+
}
590
+
// Once all comments for a post are deleted, the post can be deleted.
591
+
let deletePostResult =try await Amplify.API.mutate(request: .delete(post))
592
+
guard case .success = deletePostResult else {
593
+
print("API response: \(deletePostResult)")
594
+
return
595
+
}
596
+
print("Deleted comment and post")
597
+
} catch {
598
+
print("Failed to delete comment or post", error)
599
+
}
600
+
```
601
+
602
+
</Block>
603
+
604
+
</InlineFilter>
605
+
505
606
## Many-to-many relationships
506
607
507
608
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.
@@ -645,6 +746,40 @@ This example illustrates the complexity of working with multiple sequential crea
645
746
646
747
</InlineFilter>
647
748
749
+
<InlineFilter filters={["swift"]}>
750
+
751
+
<Block>
752
+
753
+
```swift
754
+
do {
755
+
let post = Post(title: "My Post", rating: 10)
756
+
let user = User(username: "User")
757
+
let postEditor = PostEditor(post: post, user: user)
758
+
759
+
let createPostResult = try await Amplify.API.mutate(request: .create(post))
760
+
guard case .success = createPostResult else {
761
+
print("API response: \(createPostResult)")
762
+
return
763
+
}
764
+
let createUserResult = try await Amplify.API.mutate(request: .create(user))
765
+
guard case .success = createUserResult else {
766
+
print("API response: \(createUserResult)")
767
+
return
768
+
}
769
+
let createPostEditorResult = try await Amplify.API.mutate(request: .create(postEditor))
770
+
guard case .success = createPostEditorResult else {
771
+
print("API response: \(createPostEditorResult)")
772
+
return
773
+
}
774
+
} catch {
775
+
print("Failed to create post, user, or post editor", error)
776
+
}
777
+
```
778
+
779
+
</Block>
780
+
781
+
</InlineFilter>
782
+
648
783
## Customizing query depth with custom selection sets
649
784
650
785
You can perform a nested query through one network request, by specifying which connected models to include. This is achieved by using the optional `includes` parameter for a GraphQL request.
@@ -726,6 +861,36 @@ This will populate the selection set of the post in the GraphQL document which i
726
861
727
862
</InlineFilter>
728
863
864
+
<InlineFilter filters={["swift"]}>
865
+
866
+
<Block>
867
+
868
+
```swift
869
+
do {
870
+
let queryCommentResult = try await Amplify.API.query(request:
871
+
.get(Comment.self,
872
+
byIdentifier: "c1",
873
+
includes: { comment in
874
+
[comment.post]
875
+
}))
876
+
guard case .success(let queriedCommentOptional) = queryCommentResult,
877
+
let queriedComment = queriedCommentOptional,
878
+
let loadedPost = try await queriedComment.post else {
879
+
print("API response: \(queryCommentResult)")
880
+
return
881
+
}
882
+
883
+
print("Post: ", loadedPost)
884
+
} catch {
885
+
print("Failed to query comment with post", error)
886
+
}
887
+
```
888
+
This will populate the selection set of the post in the GraphQL document which indicates to your GraphQL service to retrieve the post model as part of the operation. Once the comment is loaded, the post model is immediately available in-memory without requiring an additional network request.
889
+
890
+
</Block>
891
+
892
+
</InlineFilter>
893
+
729
894
Query for the `Post` and the first page of comments for the post:
730
895
731
896
<InlineFilter filters={["android"]}>
@@ -836,11 +1001,11 @@ This query fetches a comment, eagerly loading the parent post and first page of
0 commit comments