Update relation children within a controller. Liking protocol

System Information
  • Strapi Version: 3.6.3
  • Operating System: Windows
  • Database: MongoDB
  • Node Version:
  • NPM Version: 6.14.13
  • Yarn Version:

I am trying to implement a liking system in my platform. I have created a collection called Post that has a many to many relation with Users called liked_posts. Each time a user likes a post, it would add that post to the liked_posts relation if the user has not liked the post before, or it would delete the post from liked_posts otherwise. I am trying to create a new endpoint /posts/like/:id, where id is the id of the post which the user liked. Currently I have the following controller for that endpoint:

	async like(ctx) {
		const { post_id } = ctx.params;
		const user = ctx.state.user;
		
		// Check if user is authenticated
		if (!user) {
			return ctx.badRequest(null, [{ messages: [{ id: 'No authorization header was found' }] }]);
		}
		
		// Retrieve liked posts of the user
		let liked_posts = await strapi.query('user', 'users-permissions').findOne({ id: ctx.state.user.id });
		// Check if user already liked the post
		var index = liked_posts["liked_posts"].indexOf(post_id);
		
		if (index > -1) {
			// User already liked the post
			// We need to remove post_id from liked_posts relation
			??
		} else {
			// User did not like the post
			// We need to add post_id to liked_posts relation
			??
		}
	}

I am unable to code the parts indicated by ??. How do I modify a many to many relation in order to add or remove an element?

I have tried using liked_posts["liked_posts"].splice(index, 1); to remove the post and liked_posts["liked_posts"].push(post_id); to add the post with no success.

Thank you.

Okay, so I reviewed again the docs, and this is the best solution I achieved:

add this to post.js inside controller folder of post

	async like(ctx) {
		// Get ID of post
		const { post_id } = ctx.params;
		// Get user liking the post
		const user = ctx.state.user;

		// Check if user is logged
		if (!user) {
			return ctx.badRequest(null, [{ messages: [{ id: 'No authorization header was found' }] }]);
		}
		
		// Find the liked posts from the user
		let userQuery = await strapi.query('user', 'users-permissions');
		let liked_posts = await userQuery.findOne({ id: user.id }).then(res => res["liked_posts"]);
		
		// Check if the post is already liked
		var index = liked_posts.map(el => el.id.toString()).indexOf(post_id.toString());
		
		if (index > -1) {
			// If post already liked by user
			liked_posts.splice(index, 1);
		} else {
			// If post not liked by user
			liked_posts.push(post_id.toString());
		}
		
		// Update liked post from user
		userQuery.update({ id: user.id }, { liked_posts: liked_posts});
	}

put this inside routes.json in config folder of post:


    {
      "method": "PUT",
      "path": "/posts/like/:post_id",
      "handler": "post.like",
      "config": {
        "policies": []
      }
    }

Add ctx.response.status = 200; to send OK response when successful

Hello, I know this post is a bit older, but can someone point me in a direction as to how to do this in Strapi v4? I’ve got it running up to the last update statement where I get an error stating that “The promise rejected with the reason: Error: Update requires a data object”

1 Like