Chats and messages in GraphQL

We have introduced some new entities with messages and chats. Let's include those in our Apollo schema. In the following code, you can see an excerpt of the changed entities, fields, and parameters of our GraphQL schema:

type User {
id: Int
avatar: String
username: String
}

type Post {
id: Int
text: String
user: User
}

type Message {
id: Int
text: String
chat: Chat
user: User
}

type Chat {
id: Int
messages: [Message]
users: [User]
}

type RootQuery {
posts: [Post]
chats: [Chat]
}

Take a look at the following short changelog of our GraphQL schema:

  • The User type received an id field, thanks to our database.
  • The Message type is entirely new. It has a text field like a typical message, and user and chat fields, which are requested from the referenced tables in the database model.
  • The Chat type is also new. A chat has a list of messages that are returned as an array. These can be queried through the chat ID saved in the message table. Furthermore, a chat can have an unspecified number of users. The relationships between users and chats are saved in our separate join table, as stated previously. The interesting thing here is that our schema does not know anything about this table; it is just for our internal use, to save the data appropriately in our MySQL server.
  • I have also added a new RootQuery, called chats. This query returns all of a user's chats.

These factors should be implemented in our resolvers, too. Our resolvers should look as follows:

Message: {
user(message, args, context) {
return message.getUser();
},
chat(message, args, context) {
return message.getChat();
},
},
Chat: {
messages(chat, args, context) {
return chat.getMessages({ order: [['id', 'ASC']] });
},
users(chat, args, context) {
return chat.getUsers();
},
},
RootQuery: {
posts(root, args, context) {
return Post.findAll({order: [['createdAt', 'DESC']]});
},
chats(root, args, context) {
return User.findAll().then((users) => {
if (!users.length) {
return [];
}

const usersRow = users[0];

return Chat.findAll({
include: [{
model: User,
required: true,
through: { where: { userId: usersRow.id } },
},
{
model: Message,
}],
});
});
},
},

Let's go through the changes, one by one, as follows:

  1. I added the new RootQuery, called chats, to return all fields, as in our schema:
    • Until we get a working authentication, we will statically use the first user when querying for all chats.
    • We are using the findAll method of Sequelize and joining the users of any returned chat. For this, we use the include property of Sequelize on the user model within the findAll method. It runs a MySQL JOIN, and not a second SELECT query.
    • Setting the include statement to required runs an INNER JOIN and not a LEFT OUTER JOIN, by default. Any chat that does not match the condition in the through property is excluded. In our example, the condition is that the user ID has to match.
    • Lastly, we join all available messages for each chat in the same way, without any condition.
  2. We added the Chat property to the resolvers object. There, we ran the getMessages and getUsers functions, to retrieve all of the joined data. All messages are sorted by the ID in ascending order (to show the latest message at the bottom of a chat window, for example).
  3. We added the Message property to our resolvers.

It is important that we are using the new models here. We should not forget to extract them from the db.models object inside of the resolver function. It must look as follows:

const { Post, User, Chat, Message } = db.models;

After saving all of the files, you can start the backend (or, it should restart automatically). You can send this GraphQL request to test the changes:

{
"operationName":null,
"query": "{ chats { id users { id } messages { id text user { id username } } } }",
"variables":{}
}

The response should give us an empty chats array, as follows:

{
"data": {
"chats": []
}
}

The empty array was returned because we do not have any chats or messages in our database. You will see how to fill it with data in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.65.65