Ishwar Patil
Ishwar Patil

Reputation: 1736

Strapi CMS: Fetch Nested Content

I am using Strapi CMS and struggling with fetching the nested/deep content’s data. E.g.: Let’s say, I have below content types created and relations are defined.

Person: Name, Age

Address: City, Country

Contact: Code, Number

Person has one Address

Address has many Contacts

Now the problem is, when I access ‘/persons’, I get only Name, Age and Address object. But address object does not have the contact information associated with the address.

Can somebody help me to get this resolved or point me towards any such article?

Upvotes: 9

Views: 16858

Answers (6)

atazmin
atazmin

Reputation: 5697

This seem to work for me, Strapi v.4

Fetch components and dynamic zone components, using https://www.npmjs.com/package/qs

export async function getStaticProps({ params }) {
  const query = qs.stringify(
    {
      populate: [
        "pageHeading",
        "seo",
        "socialMedia",
        "block.image",
        "block.addressCard.image",
      ],
    },
    {
      encodeValuesOnly: true,
    }
  );
  const { data } = await fetcher(
    `${process.env.NEXT_PUBLIC_STRAPI_API}/pages?publicationState=live&${query}&filters[slug]=${params.slug}`
  );

  return { props: { data } };
}

"pageHeading" - component

"block.addressCard.image" - addressCard nested component inside dynamic zone component

enter image description here enter image description here

More at: https://documentation-git-fixes-population-strapijs.vercel.app/developer-docs/latest/developer-resources/database-apis-reference/rest/populating-fields.html#component-dynamic-zones

Upvotes: 0

Hekmat
Hekmat

Reputation: 1991

This one worked for me

let populate = ["parentCollection", "parentCollection.fieldToBePopulated"]
return await strapi.services.grandParentCollection.find({ condition }, populate)

Upvotes: 0

Moiz Sohail
Moiz Sohail

Reputation: 648

Only this worked for me

const data = await strapi
  .query("grand_collection")
  .model.find({ user: id })
  .populate({ path: "parent_collection", populate: { path: "child_collection" } });

Upvotes: 1

Tom
Tom

Reputation: 369

None of the above answers worked for me unfortunately. I have a deeply nested relation that wasn't even show in the response(some people do get ID but I got nothing in the response).

Only thing that helped me was to build controller based off the suggestion in this issue here

Upvotes: 0

Mykhaylo
Mykhaylo

Reputation: 39

I was able to get some nested data using the following:

api/booking/controllers/booking.js:

async find(ctx) {
    const entities = await strapi.services.booking.find(ctx.query, [
        'class',
        'class.capacity',
        'class.date',
        'class.category',
        'class.category.name',
        'class.type',
        'class.type.name',
        'class.startTime',
        'class.endTime',
      ]);
    }

    return entities.map((entity) =>
      sanitizeEntity(entity, { model: strapi.models.booking }),
    );
  },

where my booking has a relation to class and user. So, by default it just comes back with the class id's - but I'd like to be able to see fields from the class relation all in the same payload.

ie, instead of this:

user: "123eqwey12ybdsb233",
class: "743egwem67ybdsb311"

I'm trying to get:

user: {
  id: "123eqwey12ybdsb233",
  email: "[email protected]",
  ...
},
class: {
  id: "743egwem67ybdsb311",
  capacity: 10,
  type: {
    name: "Individual",
    description: "..."
    ...
  }
  ...
}

Now, the above works for non-relational fields.. but for fields that are a relation of a relation (ie. class.category and class.type), it doesn't seem to work as I would've expected.

In my database, the relation chain is like so: booking -> class -> category / type, where category and type each have a name and some other fields.

Upvotes: 4

Roland Balogh
Roland Balogh

Reputation: 231

Firstly you'll need a custom controller function for this. In /api/person/controllers/Person.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('person').find(ctx.query, ['address', 'contact']);
  },
};

Another solution works for me as well:

module.exports = {
  find: ctx => {
    return strapi.query('person').find(ctx.query, [
       { path: 'address' },
       { path: 'contact' },
    ]);
  },
};

Edited example with one level deeper populate:

module.exports = {
  find: ctx => {
    return strapi.query('person').find(ctx.query, [
      {
        path: 'address',
        populate: {
          path: 'contacts',
        },
      },
    ]);
  },
};

For reference see the most recent beta docs:

https://strapi.io/documentation/3.0.0-beta.x/concepts/queries.html#api-reference

Upvotes: 18

Related Questions