11

很简单(我希望)。我希望能够使用 API 端点并让它只返回指定的字段。像这样的IE

http://localhost:1337/api/reference?select=["name"]

理想情况下会返回某种形式

[{"name": "Ref1"}]

不幸的是,事实并非如此,实际上它返回以下内容。

[
{
"contributors": [
{
"username": "aduensing",
"email": "standin@gmail.com",
"lang": "en_US",
"template": "default",
"id_ref": "1",
"provider": "local",
"id": 1,
"createdAt": "2016-07-28T19:39:09.349Z",
"updatedAt": "2016-07-28T19:39:09.360Z"
}
],
"createdBy": {
"username": "aduensing",
"email": "standin@gmail.com",
"lang": "en_US",
"template": "default",
"id_ref": "1",
"provider": "local",
"id": 1,
"createdAt": "2016-07-28T19:39:09.349Z",
"updatedAt": "2016-07-28T19:39:09.360Z"
},
"updatedBy": {
"username": "aduensing",
"email": "standin@gmail.com",
"lang": "en_US",
"template": "default",
"id_ref": "1",
"provider": "local",
"id": 1,
"createdAt": "2016-07-28T19:39:09.349Z",
"updatedAt": "2016-07-28T19:39:09.360Z"
},
"question": {
"createdBy": 1,
"createdAt": "2016-07-28T19:41:33.152Z",
"template": "default",
"lang": "en_US",
"name": "My Question",
"content": "Cool stuff, huh?",
"updatedBy": 1,
"updatedAt": "2016-07-28T19:45:02.893Z",
"id": "579a5ff83af4445c179bd8a9"
},
"createdAt": "2016-07-28T19:44:31.516Z",
"template": "default",
"lang": "en_US",
"name": "Ref1",
"link": "Google",
"priority": 1,
"updatedAt": "2016-07-28T19:45:02.952Z",
"id": "579a60ab5c8592c01f946cb5"
}
]

如果我决定一次加载 10、20、30 或更多记录,这在任何现实世界环境中都会立即成为问题,我最终加载了所需数据的 50 倍。更多带宽被用完,加载时间更慢等。

4

10 回答 10

8

我是如何解决这个问题的:

  1. 在contributor/controllers/contributor.js 中创建自定义控制器操作(例如,'findPaths')
    module.exports = {
       findPaths: async ctx => {
           const result = await strapi
               .query('contributor')
               .model.fetchAll({ columns: ['slug'] }) // here we wait for one column only
           ctx.send(result);
       }
    }
  1. 在贡献者/config/routes.json 中添加自定义路由(例如“路径”)
    {
      "method": "GET",
      "path": "/contributors/paths",
      "handler": "contributor.findPaths",
      "config": {
        "policies": []
      }
    },
  1. 在管理面板中为贡献者实体添加权限,路径操作

而已。现在它只显示slug所有贡献者记录中的字段。

http://your-host:1337/contributors/paths
于 2020-08-24T08:39:23.017 回答
3

这是您如何返回特定字段并排除关系以优化响应的方法。

  async list (ctx) {
    const result = await strapi.query('article').model.query(qb => {
          qb.select('id', 'title', 'link', 'content');
      }).fetchAll({
          withRelated: []
      }).catch(e => {
          console.error(e)
      });

    if(result) {
        ctx.send(result);
    } else {
        ctx.send({"statusCode": 404, "error": "Not Found", "message": "Not Found"});
    }
  }
于 2021-02-08T06:52:37.780 回答
3

我知道这是旧线程,但我遇到了完全相同的问题,但找不到任何解决方案。文档或其他任何地方都没有。

在控制台记录和使用服务几分钟后,我能够使用以下代码过滤我的字段:

const q = Post
  .find()
  .sort(filters.sort)
  .skip(filters.start)
  .limit(filters.limit)
  .populate(populate);

return filterFields(q, ['title', 'content']);

filterFields以下功能 在哪里:

function filterFields(q, fields) {
  q._fields = fields;
  return q;
}

这是一个肮脏的解决方案,我还没有想出如何将它应用于包含的关系实体,但我希望它可以帮助寻找这个问题的解决方案的人。

我不确定为什么strapi 不支持这一点,因为它显然能够在明确设置字段时过滤它们。像这样使用它会很好:

return Post
      .find()
      .fields(['title', 'content'])
      .sort(filters.sort)
      .skip(filters.start)
      .limit(filters.limit)
      .populate(populate);
于 2018-06-29T10:53:39.277 回答
1

此功能尚未在 Strapi 中实现。作为补偿,对您来说最好的选择可能是使用 GraphQL ( http://strapi.io/documentation/graphql )。

随意创建问题或提交拉取请求:https ://github.com/wistityhq/strapi

于 2016-07-29T07:50:10.063 回答
1

让查询选择字段而不是依靠节点来删除内容会更好。但是,我发现这在某些情况下很有用,并认为我会分享。Strapi sanitizeEntity函数可以包含额外的选项,其中之一允许您只包含您需要的字段。类似于手动删除字段,但这样做的功能更可重用。

const { sanitizeEntity } = require('strapi-utils');

let entities = await strapi.query('posts').find({ parent: parent.id })

return entities.map(entity => {
  return sanitizeEntity(entity, {
    model: strapi.models['posts'],
    includeFields: ['id', 'name', 'title', 'type', 'parent', 'userType']
  });
});
于 2021-07-08T16:47:52.243 回答
0

如果您使用的是 MongoDB 数据库,则可以使用 select 函数:
await strapi.query('game-category').model.find().select(["Code"])
如您所见,我有一个名为 game 的模型-category,我只需要“代码”字段,所以我使用了 Select 函数。

于 2020-11-25T14:14:38.970 回答
0

是的,我记得另一种方式。您可以使用 xx.settings.json 文件中的属性。

参考: 模型选项

{
  "options": {
    "timestamps": true,
    "privateAttributes": ["id", "created_at"],   <-this is fields you dont want to return
    "populateCreatorFields": true    <- this is the system fields,set false to not return
  }
}
于 2021-01-29T23:20:46.747 回答
0

在当前的 Strapi 版本(3.x,不确定以前的版本)中,这可以使用自定义查询中的 select 方法来实现,而不管使用的是哪个 ORM。

SQL 示例:

 const restaurant = await strapi
    .query('restaurant')
    .model.query((qb) => {
        qb.where('id', 1);
        qb.select('name');
    })
    .fetch();
于 2020-11-25T17:45:52.753 回答
0

不是很漂亮,但您可以在返回之前将其删除。

参考这里: https ://strapi.io/documentation/developer-docs/latest/guides/custom-data-response.html#apply-our-changes

const { sanitizeEntity } = require('strapi-utils');

module.exports = {
  async find(ctx) {
    let entities;
    if (ctx.query._q) {
      entities = await strapi.services.restaurant.search(ctx.query);
    } else {
      entities = await strapi.services.restaurant.find(ctx.query);
    }

    return entities.map(entity => {
      const restaurant = sanitizeEntity(entity, {
        model: strapi.models.restaurant,
      });
      if (restaurant.chef && restaurant.chef.email) {
        **delete restaurant.chef.email;**
      }
      return restaurant;
    });
  },
};
于 2021-01-29T23:04:40.430 回答
0

您可以覆盖默认的strapi实体响应:-

entity = await strapi.services.weeklyplans.create(add_plan);

return sanitizeEntity(entity, { model: strapi.models.weeklyplans });

通过使用:-

ctx.response.body = { 
              status: "your API status", 
              message: "Your own message" 
        }

使用 ctx 对象,我们可以选择我们想要显示为对象的字段。并且不需要返回任何东西。将 放置ctx.response.body在条件满足时必须发送响应的位置。

于 2021-06-02T08:50:06.633 回答