如何在Strapi中为GraphQL添加自定义查询以支持按name查询Course?
解决Strapi中GraphQL查询支持name参数的问题
你说得没错,Strapi默认生成的GraphQL course 查询只支持id作为参数,要实现通过name查询,确实需要自定义查询逻辑。下面我给你一步步拆解怎么操作:
1. 编写自定义控制器方法
首先在api/course/controllers/course.js(如果没有就新建这个文件)里添加一个根据name查询课程的方法:
module.exports = { // 自定义根据name查询课程的方法 async findByName(ctx) { // 从请求参数里获取name const { name } = ctx.params; // 调用Strapi的service层查询对应课程 const course = await strapi.services.course.findOne({ name }); if (!course) { return ctx.notFound('Course not found'); } return course; }, };
2. 配置对应的API路由
接下来在api/course/config/routes.json(没有则新建)里添加路由映射,让这个控制器方法能被访问到:
{ "routes": [ { "method": "GET", "path": "/courses/name/:name", "handler": "course.findByName", "config": { "policies": [] } } ] }
3. 扩展GraphQL Schema并添加Resolver
现在要让GraphQL识别这个新的查询,需要做两步:
3.1 定义GraphQL查询类型
在api/course/config/schema.graphql(没有则新建)里添加扩展的查询定义:
extend type Query { # 定义新的查询,参数name是必填字符串,返回Course类型 courseByName(name: String!): Course }
3.2 编写Resolver映射
创建api/course/config/resolver.js文件,把GraphQL查询和控制器方法关联起来:
module.exports = { Query: { courseByName: async (parent, args, ctx) => { // 从GraphQL参数里拿到name const { name } = args; // 调用我们刚才写的控制器方法 return await strapi.api.course.controllers.course.findByName({ params: { name }, }); }, }, };
4. 重启Strapi服务
修改完这些配置和代码后,一定要重启你的Strapi服务,这样新的查询逻辑才能生效。
5. 测试新的GraphQL查询
现在你就可以用新的查询语句来根据name获取课程了:
{ courseByName(name: "course1") { name description modules { title } } }
额外选项:修改默认course查询支持name参数
如果你不想新增courseByName查询,而是希望原来的course查询同时支持id和name参数,可以这么做:
- 覆盖默认的
findOne控制器方法:
module.exports = { async findOne(ctx) { const { id, name } = ctx.params; let query = {}; // 判断传入的是id还是name if (id) { query = { id }; } else if (name) { query = { name }; } else { return ctx.badRequest('请提供id或name参数'); } const course = await strapi.services.course.findOne(query); if (!course) { return ctx.notFound('Course not found'); } return course; }, };
- 修改GraphQL Schema,让
course查询接受name参数:
extend type Query { course(id: ID, name: String): Course }
不过这里要注意,因为原来的course查询默认要求id必填,所以修改后要把id设为可选,同时name也设为可选,这样就能支持两种参数查询了。
因为你的name字段设置了unique: true,所以用name查询只会返回唯一结果,这样的设计是完全合理的。
内容的提问来源于stack exchange,提问作者Swogget
相关产品推荐
相关产品推荐

