使用GraphQL+Elasticsearch开发待办App时,任务完成状态切换逻辑失效问题求助
GraphQL+Elasticsearch开发待办App时,任务完成状态切换逻辑失效问题求助
我最近在开发一个待办事项App,遇到了一个棘手的问题:点击任务想要切换它的完成状态(已完成true切换为未完成false,未完成false切换为已完成true)。之前没有接入GraphQL的时候,这套逻辑运行完全正常,但现在用GraphQL配合Elasticsearch实现后,状态切换功能就失效了。我已经尝试把原来的if-else判断改成用!task.done的简写方式,但问题还是没有解决。
以下是我的相关代码,麻烦帮忙看看哪里出了问题:
1. GraphQL Schema 定义
const { makeExecutableSchema } = require('@graphql-tools/schema'); const { resolvers } = require('./resolvers'); const typeDefs = `#graphql type Query { tasks: [Task!]! } type Mutation{ newTask( input: taskInput!): Task updatedTask( id: ID!): Task deletedTask( id: ID!): Task } input taskInput{ name: String!, } type Task { name: String! done: Boolean! id: ID! } ` const schema = makeExecutableSchema({ typeDefs, resolvers }); module.exports = {schema}
2. Resolvers 实现
const { client } = require('./controllers/tasks'); const resolvers = { Query: { tasks: async (parent, args, context, info) => { const result = await client.search({ index: 'tasks', body: { query: { match_all: {} } } }); const tasks = result.hits.hits.map((hit) => hit._source); return tasks } }, Mutation: { deletedTask: async (parent, args, context, info) => { const id = args.id await client.delete({ index: 'tasks', id: id, }); }, updatedTask: async (parent, args, context, info) => { const id = args.id const task = await client.get({ index: 'tasks', id: id }); console.log(task.done) // 这里打印出来的应该是undefined? await client.update({ index: 'tasks', id: id, body: { doc: { done: !task.done } } }); }, newTask: async (parent, args, context, info) => { const { input } = args; const newTask = { name: input.name, done: false }; const result = await client.index({ index: 'tasks', body: newTask }); const { _id } = result; newTask._id = _id; return newTask; } } }; module.exports = { resolvers };
问题排查与修正建议
我注意到一个很可能的问题:Elasticsearch客户端的get方法返回的结果结构里,任务的源数据是存放在_source字段中的,而不是直接在返回对象的顶层。
你现在的代码里直接用task.done去获取状态值,实际上这个值是undefined,因为正确的路径应该是task._source.done。当你对undefined取反时,结果会是true,所以每次更新都会把done设为true,导致状态切换逻辑完全失效。
修正后的updatedTask resolver应该是这样的:
updatedTask: async (parent, args, context, info) => { const id = args.id; // 解构获取_source里的任务数据 const { _source: task } = await client.get({ index: 'tasks', id: id }); console.log(task.done); // 现在能正确打印出当前的状态值了 await client.update({ index: 'tasks', id: id, body: { doc: { done: !task.done } } }); // 另外建议返回更新后的任务数据,符合GraphQL的规范 return { ...task, id }; }
另外还有一个小细节:你的updatedTask mutation定义里,返回类型是Task,但当前代码没有返回任何数据,这也不符合GraphQL的规范,建议像上面的代码一样,返回更新后的任务对象,这样前端才能拿到最新的状态。
你可以先尝试这个修正,看看状态切换功能是否正常工作了,如果还有问题,可以把console.log(task)的结果贴出来,方便进一步排查。
备注:内容来源于stack exchange,提问作者anfield
相关产品推荐
相关产品推荐

