Closed ChristopherGabba closed 4 months ago
Hi @ChristopherGabba can you try awaiting the receiver
in your code? You may have to lazy load the relationship data.
Like so:
const firstFriendshipReceiver = await response.data[0].receiver();
Here are our docs on lazy loading hasMany relationships:
@chrisbonifacio Interesting. This worked, but it still creates an issue for me. I basically fetch the friendship (with underlying user (receiver/sender) nested data) and I apply it straight into my local state.
Now I will have to:
It would be painful and inefficient to have to create a whole other query when the user data should already be available in the same friendship api call. I noticed in the same link you provided there is an eagerly load
, which is what I'm looking for I think. How can I define a selectionSet: { selectionSet: ["id", "receiver.", "sender."] }, so that the deeper nested data just comes through initially in the first api call?
I had this working fine in a Gen 1 without having to lazy load by modifying the query in one of the amplify files locally that was created with the amplify codegen
command:
aws/graphql/queries.ts
export const friendshipsByReceiverId =
/* GraphQL */ `query FriendshipsByReceiverId(
$receiverId: ID!
$sortDirection: ModelSortDirection
$filter: ModelFriendshipFilterInput
$limit: Int
$nextToken: String
) {
friendshipsByReceiverId(
receiverId: $receiverId
sortDirection: $sortDirection
filter: $filter
limit: $limit
nextToken: $nextToken
) {
items {
id
senderId
sender { // defined deeper nested return data without lazy loading
id
profileImage
profileImageBlurhash
firstName
lastName
username
birthdate
phoneNumber
searchTerm
pushToken
createdAt
updatedAt
__typename
}
receiverId
receiver { // defined deeper nested return data without lazy loading
id
profileImage
profileImageBlurhash
firstName
lastName
username
birthdate
phoneNumber
searchTerm
pushToken
createdAt
updatedAt
__typename
}
status
createdAt
updatedAt
__typename
}
nextToken
__typename
}
}
` as GeneratedQuery<
APITypes.FriendshipsByReceiverIdQueryVariables,
APITypes.FriendshipsByReceiverIdQuery
>;
Now this file is not exposed for editting in Gen 2.
I think this is super valuable, and I doubt I am the only user who will need this. Perhaps this can be a secondaryIndex input when defining a query?
Hey @ChristopherGabba you can do "receiver.*"
in the selection to select and eagerly load all fields on a nested/related record.
Thanks @chrisbonifacio thats exactly what I was looking for! I couldn't get the selectionSet field to show up but it's actually a second object parameter input into the list query.
Is there a way to define this globally instead of in every query?
Example:
receiver: a.belongsTo("User", "receiverId").includeInSelectionSet()
The problem with it having to be defined in every query is that now if I try to reference a friendship type:
const friendship: Schema["Friendship"]["type"] = ...
const firstName = friendship.reciever.firstName // throws typescript error on firstname because the main schema won't allow me to reference the nested object data even when I know it is there.
Defining the selection sets seems to override the tyepscript for the results of the query but I want that to be global so throughout my app, I can reference things deeper without typescript errors.
@ChristopherGabba the solution here might be to define the selection set separately and combine its typing with Schema using our SelectionSet
helper type:
Here's an example:
import type { SelectionSet } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource';
const selectionSet = ['content', 'blog.author.*', 'comments.*'] as const;
type PostWithComments = SelectionSet<Schema['Post']['type'], typeof selectionSet>;
// ...
const [posts, setPosts] = useState<PostWithComments[]>([]);
const fetchPosts = async () => {
const { data: postsWithComments } = await client.models.Post.list({
selectionSet,
});
setPosts(postsWithComments);
}
@chrisbonifacio Awesome! This worked. Closing this issue as complete, thanks again for all the help, I know that Gen 2 is fairly new.
I will propose a feature request in a separate thread like so:
receiver: a.belongsTo("User", "receiverId").includeInSelectionSet()
So that custom types won't have to be defined, and you won't have to set selectionSets separately on each query, should the user not want it.
Before opening, please confirm:
JavaScript Framework
React Native
Amplify APIs
GraphQL API, DataStore
Amplify Version
v6
Amplify Categories
api
Backend
Amplify Gen 2 (Preview)
Environment information
Describe the bug
I have set up a Gen 2 backend deployment following the steps in the docs and here is my
data/resource.ts
setup:Within the app, I use my secondary index query like so:
Expected behavior
I want to be able to reference
response.data[0].receiver.firstName
but I can't reference any user properties from my friendship query.Reproduction steps
Code Snippet
Refer to issue description above.
Log output
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
iPhone 12
Mobile Operating System
iOS 17.2.1
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
Using Expo 51