You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 10:24:35