GraphQL级联删除

GraphQL级联删除,graphql,Graphql,我正在使用GraphQL,希望从数据库中删除实体和其他通过关系分配给第一个实体的实体 假设在GraphQL模式中有三种类型 使用者 分配 任务 逻辑如下:用户以某种方式与任务相关。这种关系由“中间”对象赋值表示。(在Assignment中,我可以设置该用户是任务或工作人员的主管或其他任何人,这不是重点。) 现在,我想删除用户和相关的分配(任务不应删除) 我想知道我是否可以通过只使用一个参数执行一个变异查询来做到这一点:用户ID 我在想这样的事情: mutation deleteUser($use

我正在使用GraphQL,希望从数据库中删除实体和其他通过关系分配给第一个实体的实体

假设在GraphQL模式中有三种类型

  • 使用者
  • 分配
  • 任务
  • 逻辑如下:
    用户
    以某种方式与
    任务
    相关。这种关系由“中间”对象
    赋值
    表示。(在
    Assignment
    中,我可以设置该用户是任务或工作人员的主管或其他任何人,这不是重点。)

    现在,我想删除
    用户
    和相关的
    分配
    任务
    不应删除)

    我想知道我是否可以通过只使用一个参数执行一个变异查询来做到这一点:用户ID

    我在想这样的事情:

    mutation deleteUser($userId: ID!){
      deleteUser(id: $userId){
        id
        assignment {
          id # use that id somehow below
        }
      } {
        deleteAssignment(id: id_from_above) {
        }
      }
    }
    

    这样的事情可能吗?

    我想你会从阅读这本书中受益

    如果操作是变异,则操作的结果是对变异根对象类型执行变异的顶级选择集的结果。此选择集应连续执行

    这里的关键是突变是:

    • 被认为是一种查询类型,除非它们有副作用
    • 它们不是按照方便的顺序进行的,甚至不像查询那样是并发的,而是按顺序进行的
    具体来说,您的问题是:如果删除一个用户需要在概念上同时删除该用户的分配,并且删除分配会删除所有任务,那么公开的变异(即“查询”)可能只是:

    mutation deleteUser($userId: ID!) {
      deleteUser(id: $userId)
    }
    
    而相关的删除只会发生,不需要返回任何内容。如果您确实想归还物品,可以将这些物品添加为可供查看的物品:

    mutation deleteUser($userId: ID!) {
      deleteUser(id: $userId) {
        assignment {
          task
        }
      }
    }
    
    或者,如果希望客户端控制任务和工作分配的删除,以便“查看”子删除(触发此类实际删除:

    mutation deleteUser($userId: ID!) {
      deleteUser(id: $userId) {
        deleteAssignment {
          deleteTask
        }
      }
    }
    

    当然,假设您适当地定义了变异类型以使这些字段可用,并且基础软件会相应地按照上述要求的行为进行操作。

    如果您只是希望级联删除,客户端无需执行任何操作-无需特殊查询。只需在mutat中执行适当的逻辑即可离子分解器

    例如,如果您有一个用于删除用户的服务方法,而变异解析器最终将调用该方法(示例是Java,但无论您使用何种语言(您没有提到),逻辑都是相同的):

    客户端不需要关心这一点,他们只是告诉您的系统删除用户:

    mutation deleteUser($userId: ID!){
      deleteUser(id: $userId)
    }
    
    如果您希望客户端能够获得比布尔成功标志更好的东西,请返回该东西(当然这意味着相应地更改模式):

    后者允许客户端查询结果(这些是子查询,不是子突变,没有子突变):

    需要注意的是,与查询不同,突变不能嵌套,但是可以发送多个顶级突变(如示例所示)。遗憾的是,无法将第一个规范的结果用作第二个规范的输入。有人要求在GraphQL规范中引入此内容,但这种情况可能会发生,也可能永远不会发生

    意思是你的例子:

    mutation deleteUser($userId: ID!) {
      deleteUser(id: $userId) {
        id
        assignment {
          id # use that id somehow below
        }
      } {
    
      deleteAssignment(id: id_from_above) {
        id
      }
    }
    
    不幸的是,这是不可能的

    您必须以两个独立的请求的形式来执行此操作,或者提出一种更详细的方法。如果您需要允许客户端进行更深层次的控制,则可以接受更复杂的输入,而不仅仅是ID,例如:

    input DeleteUserInput {
      id: ID!
      deleteOwnAssignments: Boolean
      deleteManagedAssignments: Boolean
    }
    
    mutation deleteUser($input: DeleteUserInput!) {
      deleteUser(input: $input)
    }
    
    boolean deleteUser(String id, boolean deleteOwnAssignments, boolean deleteManagedAssignments) {
       if (deleteOwnAssignments) {
           dataBase.execute("DELETE FROM Assignment WHERE assigned_to = :id");
       }
       if (deleteManagedAssignments) {
           dataBase.execute("DELETE FROM Assignment WHERE manager_id = :id");
       }
       dataBase.execute("DELETE FROM User WHERE id = :id");
       return true; //or return whatever is appropriate
    }
    

    下面提供的答案对您有用吗?如果没有,请评论,我很乐意改进。如果是,您可以接受它?突变不能像查询一样嵌套,因此最后一个示例要么是错误的,要么需要实际为突变的子查询。
    String deleteUser(String id) { 
       User user = dataBase.execute("SELECT FROM User WHERE id = :id");   
       dataBase.execute("DELETE FROM User WHERE id = :id");
       //return the whole deleted user
       return user;
    }
    
    mutation deleteUser($userId: ID!){
      deleteUser(id: $userId) {
        id
        assignments {
          id
        }
      }
    }
    
    mutation deleteUser($userId: ID!) {
      deleteUser(id: $userId) {
        id
        assignment {
          id # use that id somehow below
        }
      } {
    
      deleteAssignment(id: id_from_above) {
        id
      }
    }
    
    input DeleteUserInput {
      id: ID!
      deleteOwnAssignments: Boolean
      deleteManagedAssignments: Boolean
    }
    
    mutation deleteUser($input: DeleteUserInput!) {
      deleteUser(input: $input)
    }
    
    boolean deleteUser(String id, boolean deleteOwnAssignments, boolean deleteManagedAssignments) {
       if (deleteOwnAssignments) {
           dataBase.execute("DELETE FROM Assignment WHERE assigned_to = :id");
       }
       if (deleteManagedAssignments) {
           dataBase.execute("DELETE FROM Assignment WHERE manager_id = :id");
       }
       dataBase.execute("DELETE FROM User WHERE id = :id");
       return true; //or return whatever is appropriate
    }