how to filter many to many relation in strapi

I have two content-type in strapi like tag and article. And want to filter articles which both have several tags like 1,2,4. In the standard strapi, you cannot do this .so I have to change the default behavior of strapi article api. you can find the document in here

first

we need to define the special parameter to reach our goals. in fact I choose the multiTag in the query parameter

query{
	multiTag: [1,2,3]	
}

second

open file in your project

/src/api/article/controllers/article.js

! notice: the path would change with your content-type name.

you should get this

const { createCoreController } = require('@strapi/strapi').factories;

module.exports = createCoreController('api::article.article');

then add some code to this

async function getMultiTag(conn, multiTag){
	// the sql should like this 
	const sql = `
		select 
			t.id 
		from 
			article t 
		inner join (
			select article_id from article_link_tag 
			where tag_id in (${string(multiTag})
			group by article_id having count(*) = ${multiTag.length}
		) t2 on t.id = t2.article_id
	`
	const result = await conn.raw(sql)
	// result should like this 

[
	// actual data
	[
		{"id" : 1}	
	],
  // meta info
	[
	{
		"db" : 1
	}
	]
]
	return result[0]
}

module.exports = createCoreController('api::pet-article.pet-article', ({ strapi }) => ({
   async find(ctx) {
    ctx.query = { ...ctx.query, local: 'en' }
		// get the param
    const multiTag = ctx.query?.multiTag
    if (multiTag && typeof multiTag == 'object' && multiTag.length > 0) {
			// get the database connection
      const conn = strapi.db.connection
      const articles = await getMultiTag(conn, multiTag)
			// when you have got the ids of article 
			// you can do many things
			// like this 
			ctx.query.filter = {
				...(ctx.query.filter || {}),
				id: {
					$in: articles.map(val => val.id)
				}
			}
			// or just return the ids
			// return { data: articles }
    }
    const { data, meta } = await super.find(ctx);
    meta.date = Date.now()
    return { data, meta };
  },
}));