Strapi CMS:获取嵌套内容

9
我正在使用Strapi CMS,并且在获取嵌套/深层内容数据方面遇到了困难。 例如:假设我创建了以下内容类型并定义了关系。
人员:姓名,年龄
地址:城市,国家
联系方式:代码,号码
人员有一个地址
地址有多个联系方式
现在的问题是,当我访问“/persons”时,我只能获得姓名、年龄和地址对象。但地址对象没有与地址相关联的联系方式信息。
有人能帮助我解决这个问题或指向任何类似的文章吗?
6个回答

18

首先您需要为此编写自定义控制器函数。 在/api/person/controllers/Person.js中,您可以导出自定义的查找函数。 在那里,您可以定义要填充哪些字段:

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

还有另一种解决方案也适合我:

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

通过一个更深层级的populate编辑示例:

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

参考最新的测试版文档:

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


谢谢你的建议,Roland。我会尝试使用它。但是我在想,如果我想要改变模式结构并添加一些更嵌套的模式,该怎么办呢?我将不得不再次更改控制器来解决这个问题。如果我有多个这样的高级模式和嵌套模式,该怎么办呢?是否有动态处理此类情况的解决方案? - Ishwar Patil
好问题。在字段中,我找到了两个可以尝试的模式定义字段。一个是autoPopulate(布尔类型),另一个是private(布尔类型)。不幸的是,我没有在文档中找到有关这些字段的信息,但是这里是我第一次看到它们的问题和评论:https://github.com/strapi/strapi/issues/2086#issuecomment-428176026如果您有多层深度,例如:您的地址有许多联系人,您可以扩展查询以添加更多填充字段。我会更新答案。 - Roland Balogh
你必须在 async 函数内部调用 strapi.query() 之前添加 await。 - Victor Ray
不一定。在这里,我们立即返回查询(和结果),只想将其发送到响应中。Strapi会处理剩下的部分。也许我们甚至可以在这里删除async,我只是总是把它放在那里,如果我想在发送响应之前使用数据,因为在这种情况下需要等待。 - Roland Balogh
@RolandBalogh,我也遇到了一些问题,我收到了401未经授权的错误,我认为这是因为我创建了一个数据所有权的自定义策略。有没有办法在查询中包含该策略,以便我不会出现错误?如果我删除自定义控制器方法,我就可以轻松获取数据(但我无法填充更深层次)。 - Fjallbacka
@Fjallbacka能否写更多关于你的自定义策略的信息?或者它是什么样子的?在你的策略文件夹中创建了什么? - Roland Balogh

4

我能够使用以下方法获取一些嵌套数据:

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 }),
    );
  },

我的 bookingclassuser 有关系。所以,默认情况下,它只返回类别 id 的信息,但我希望能够在同一负载中查看来自类别关系的字段。

即,不是这样的:

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

我正在尝试获得:

user: {
  id: "123eqwey12ybdsb233",
  email: "foo@bar.com",
  ...
},
class: {
  id: "743egwem67ybdsb311",
  capacity: 10,
  type: {
    name: "Individual",
    description: "..."
    ...
  }
  ...
}

现在,以上方法适用于非关系字段...但对于那些是关系的关系字段(例如:class.categoryclass.type),它似乎不起作用,这并不是我期望的结果。

在我的数据库中,关系链如下:booking -> class -> category / type,其中categorytype都有一个name和一些其他字段。


嗨,我目前在嵌套用户方面遇到了一些问题,即使我使用sanitizeEntity,它仍然返回密码,这是否是预期的?如果有实用程序函数可以做到这一点,我更愿意不手动剥离它,因为这是相当常见的。为了适应这种情况,我的“用户”位于“预订”对象中,以指示其属于谁的预订。 - Zennichimaro
1
@Zennichimaro 你使用什么模型进行消毒?以下是我在应用程序中完成类似情况的方法: // booking.author 目前只是 ID 字符串,因此我们需要获取完整的关系对象 const author = strapi.query('user', 'users-permissions').findOne({ id: booking.author }, []); // 使用完整的用户对象更新 booking.author 并进行消毒 booking.author = sanitizeEntity(user, { model: strapi.plugins['users-permissions'].models.user });``` - Mykhaylo

1

只有这个对我起作用了

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

0

这对我来说似乎有效,Strapi v.4

使用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" - 组件

"block.addressCard.image" - 地址卡嵌套在动态区组件内的组件

enter image description here enter image description here

更多信息请参见: https://documentation-git-fixes-population-strapijs.vercel.app/developer-docs/latest/developer-resources/database-apis-reference/rest/populating-fields.html#component-dynamic-zones


0

这个对我有用

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

0

很不幸,以上的答案都对我没用。

我有一个深度嵌套的关系,在响应中甚至没有显示(有些人会得到ID,但我在响应中什么也没有)。

唯一帮助我的是根据这个问题这里的建议构建控制器。


也许您可以提供更多关于您问题的上下文。 - Moiz Sohail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接