Can you apply sorting to a lists of models inside another model?

Viewed 31

Using AWS Amplify, can we apply sorting to the messages in the Conversation model? When fetching the conversation, it would be nice that the messages come sorted based on the generated createdAt date.

Currently these are the models used.

type Conversation @model {
  id: ID!
  messages: [Message!]! @hasMany
  ...
}

type Message @model {
  id: ID!
  authorId: String!
  content: String!
  conversation: Conversation @belongsTo
}

Ideally want to place sorting on the hasMany directive, but this is not possible.

type Conversation @model {
  id: ID!
  messages: [Message!]! @hasMany(sortKeys:['createdAt'])
  ...
}
1 Answers

Created a secondary index on the Message model with a sort field on createdAt.

type Message @model {
  id: ID!
  authorId: String! @index(name: "byAuthorId", queryField: "getMessagesByAuthorId", sortKeyFields: [ "createdAt" ])
  content: String!
  conversation: Conversation @belongsTo
}

Amplify created a new query to fetch the messages and apply sorting. Following example uses react-query to fetch the messages from an authorId with sorting.

export function useMessagesPerAuthorId({
  id,
  filter,
  enabled = true,
}: {
  id: string | undefined;
  filter: any;
  enabled?: boolean;
}) {
  return useQuery(
    ['conversations', 'messages', id, filter],
    () => fetchMessagesByAuthorId({ id: id!, filter }),
    { enabled: enabled && !!id }
  );
}

async function fetchMessagesByAuthorId({ id, filter }: { id: string; filter: any }) {
  const query: any = await API.graphql({
    query: getMessagesByAuthorId,
    variables: { authorId: id, sortDirection: 'DESC', filter },
  });

  const data: Message[] = query.data?.getMessagesByAuthorId.items;

  return data;
}

Now we can call that hook in our view component and pass the filters.

const { isLoading, data: messages = [] } = useMessagesPerAuthorId({
    id: profile?.id,
    filter: {
      and: [{ conversationMessagesId: { eq: conversationId } }, { deleted: { eq: false } }],
    },
    enabled: !!profile?.id,
  });
Related