Strapi CMS: получение вложенного содержимого

Я использую Strapi CMS и не могу получить данные вложенного / глубокого контента. Например: Скажем, у меня ниже созданы типы контента и определены отношения.

Человек: Имя, Возраст

Адрес: Город, Страна

Контакты: Код, Номер

У человека один адрес

Адрес имеет много контактов

Теперь проблема в том, что когда я обращаюсь к «/ people», я получаю только объект Name, Age и Address. Но адресный объект не имеет контактной информации, связанной с адресом.

Может ли кто-нибудь помочь мне решить эту проблему или указать мне на какую-либо такую ​​статью?


person ivp    schedule 28.11.2019    source источник


Ответы (4)


Во-первых, для этого вам понадобится настраиваемая функция контроллера. В /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' },
    ]);
  },
};

Отредактированный пример с заполнением на один уровень глубже:

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.

person Roland Balogh    schedule 28.11.2019
comment
Спасибо за советы, Роланд. Я попробую этим воспользоваться. Однако мне интересно, что, если я хочу изменить структуру схемы и добавить еще несколько вложенных схем с помощью панели администратора. Затем мне придется снова сменить контроллер, чтобы решить эту проблему. А что, если у меня есть несколько таких схем более высокого уровня с вложенной схемой. Есть ли решение, чтобы справиться с этим динамически? - person ivp; 29.11.2019
comment
Хороший вопрос. Я нашел два поля, которые вы можете попробовать в определении схемы в полях. Один - autoPopulate (логический), а второй - private (логический). К сожалению, я не нашел информации об этом в документации, но вот проблема и комментарий, в котором я их впервые увидел: github.com/strapi/strapi/issues/2086#issuecomment-428176026 Если у вас несколько уровней глубины, например: в вашем адресе много контактов, вы можете расширить запрос до добавить дополнительные поля для заполнения. Я обновлю ответ. - person Roland Balogh; 29.11.2019
comment
Вы должны добавить ожидание перед strapi.query (). Вы вызываете внутри асинхронной функции. - person Victor Ray; 09.04.2020
comment
Не обязательно. Здесь мы немедленно возвращаемся с запросом (и результатом) и просто хотим отправить его в ответ. Остальное возьмет на себя Strapi. Возможно, мы могли бы даже удалить здесь асинхронный код, я просто всегда помещаю его туда, если я хочу работать с данными, прежде чем я отправлю ответ bc, в этом случае вам нужно await. - person Roland Balogh; 11.04.2020
comment
@RolandBalogh У меня тоже проблемы с этим, я получаю неавторизованную ошибку 401, я предполагаю, что это из-за созданной мной настраиваемой политики владения данными. Есть ли способ включить политику в запрос, чтобы я не получал сообщение об ошибке? Если я удалю метод настраиваемого контроллера, у меня не возникнет проблем с получением данных (но я не могу заполнить на один уровень глубже) - person Fjallbacka; 19.04.2020
comment
@Fjallbacka, можете ли вы написать больше информации о своей индивидуальной политике? Или как это выглядит? Что было создано в вашей папке политик? - person Roland Balogh; 23.04.2020

Мне удалось получить некоторые вложенные данные, используя следующее:

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

где мой booking имеет отношение к class и user. Итак, по умолчанию он просто возвращается с классом id, но я хотел бы видеть все поля из отношения class в одной и той же полезной нагрузке.

т.е. вместо этого:

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

Я пытаюсь получить:

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

Вышеупомянутое работает для нереляционных полей ... но для полей, которые являются отношением отношения (например, class.category и class.type), похоже, это не работает так, как я ожидал.

В моей базе данных цепочка отношений выглядит так: booking - ›class -› category / type, где у category и type есть name и некоторые другие поля.

person Mykhaylo    schedule 02.11.2020
comment
Привет, у меня сейчас проблема с вложенным пользователем, он возвращает пароль даже после того, как я использую sanitizeEntity, это ожидается? Я бы предпочел не удалять его вручную, если для этого есть служебная функция, поскольку это довольно распространено. Чтобы соответствовать этому варианту использования, мой User находится в объекте Booking, чтобы указать, чье это бронирование. - person Zennichimaro; 03.01.2021
comment
@Zennichimaro, какую модель вы используете для дезинфекции? Вот как я проделал подобный случай в своем приложении: const booking = await strapi.query('booking').findOne(params, populate); // booking.author is just the ID string at this point, so we need to get the full relation object const author = strapi.query('user', 'users-permissions').findOne({ id: booking.author }, []); // update booking.author with the full user object and sanitize it booking.author = sanitizeEntity(user, { model: strapi.plugins['users-permissions'].models.user }); - person Mykhaylo; 05.01.2021

К сожалению, ни один из приведенных выше ответов не помог мне. У меня есть глубоко вложенное отношение, которое даже не отображалось в ответе (некоторые люди получают идентификатор, но я ничего не получил в ответе).

Единственное, что мне помогло, - это создать контроллер на основе предложения в этой проблеме здесь < / а>

person Tom    schedule 10.07.2021
comment
Может быть, расскажите немного подробнее о вашей проблеме - person Moiz Sohail; 18.07.2021

Только это сработало для меня

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