Search code examples
javascriptjsonstrapi

Strapi: Get all nested properties for deeply nested relation


I recently started working with strapi and have been figuring out how to go about content relations and so on... Now I have reached a point when I have multiple content relations dependent on each other.

This is my strucute:

Collection Types:

  1. Categories
  2. Articles
    • with content relation: Article has one category

Single Types:

  1. Homepage
    • with content relation: Homepage has many articles

Now what I want to do is to to get all nested properties of a category for articles that are assigned to homepage just by simply making a GET request from /homepage

What I currently get is a json structure like this:

{
   "id": 1,
   "hero": {
    ....
   },
   "featuredArticles": {
    ....
   },
   "displayedArticles": [
      {
         "id": 2,
         "category": 5,
      }
   ]
}

What is the expected output:

{
   "id": 1,
   "hero": {
    ....
   },
   "featuredArticles": {
    ....
   },
   "displayedArticles": [
      {
         "id": 2,
         "category": [
            {
              "id": 5,
              "title": "Foundation"
            }
         ],
      }
   ]
}

My suspicion is that the properties of categories is basically too nested when trying to fetching from /homepage rather than /articles directly.

I found out that handling this could work with modifying the controllers right in the strapi directory but I haven't figured it out quite.

Strapi Controller Docs

Is here anybody who knows solution to this?


Solution

  • Firstly you'll need a custom controller function for this. In /api/homepage/controllers/homepage.js you can export your custom find function.

    There you can define which fields you want to populate:

    module.exports = {
     find: ctx => {
       return strapi.query('homepage').find(ctx.query, [
         {
           path: 'displayedArticles',
           populate: {
             path: 'category',
           },
         },
       ]);
     }
    };
    

    For reference see the most recent beta docs: Customization

    Second way: populate it as per requirement

    module.exports = {
      find: async (ctx) => {
        const homePage = await strapi.query('homepage').find(ctx.query);
        const categories = await strapi.query('categories').find();
    
        if (homePage[0].displayedArticles) {
           homePage[0].displayedArticles.forEach(async (content) => {
             if(categories){
               content.category = categories.find((category) => {
                 return category.id === content.category;
               });
             }
          });
        } 
        
        if (homePage[0].displayedComponents) {
          homePage[0].displayedComponents.forEach(async (content) => {
            if(categories){
             content.category = categories.find((category) => {
               return category.id === content.category;
              });
            }
          });
        } 
        
        return homePage;
      }
    
    };