Cascade delete upon graphQL delete query

Is cascade delete available out-of-the-box in GraphQL?
Basically, if a document is related to a parent

type User { 
  name: String
  blog: [Blog]
}

type Blog {
 content: String!
 user: User!
}

When I delete a user via GraphQL query, the related Blog documents would be deleted too.

The short answer is no, not out of the box, but you can add it yourself.

If you need cascading delete you can create a User Defined Function associated with a GraphQL mutation using the @rsolver directive.

1 Like

I guess that’s the best thing I could do. Coincidentally, do you have something I can work on?
Like the best practice for tackling such issues?

For the FQL to do this, remember that FQL is pretty much a functional style programming language. I’ve not seen any “standard” ways of doing this, but I can immediately think of how to go about doing it, because it’s just another program.

totally pretend code if FQL was just javascript:

const cascadeDeleteUser = (userRef) => {
  const userBlogRefs = blogsByUser(userRef)
  const deleteBlogsResults = userBlogRefs.map(blogRef => delete(blogRef))
  const deleteUserResult = delete(userRef)

  return true
}

So given that is what we want to do, we can add the mutation to GraphQL

type Mutation {
  cascadeDeleteUser(id: ID!): Boolean! @resolver(name: "cascadeDeleteUser")
}

Note that the GraphQL api will want just the ID, not the whole Ref. So we’ll reconstruct the Ref in the Query. Also, you can decide to return a bunch of different things, but if you just want a simple signal that it worked, then a boolean is sufficient. If you need to update a cache, then you might want to return an array of deleted Documents (which the Delete FQL function does).

The actual UDF would look like this:

{
  name: "cascadeDeleteUser",
  body: Query(
    Lambda(
      "userId",
      Let(
        {
          userRef: Ref(Collection("User"), Var("userId")),
          userBlogRefs: Paginate(Match(Index("blogs_by_user"), Var("userRef"))),
          deleteBlogsResults: Map(
            Var("userBlogRefs"),
            Lambda("ref", Delete(Var("ref")))
          ),
          deleteUserResults: Delete(Var("userRef"))
        },
        true
      )
    )
  )
}

Where the Index blogs_by_user is also something that you need to set up.

Since User-to-Blog is a one-to-many relationship, the reference will be stored in the Blog Collection – the “many” side of the relationship.

{
  name: "blogs_by_user",
  source: "Blog",
  terms: [
    {
      field: ["data", "user"]
    }
  ]
}

Regarding best practices, I just kicked off this other topic. I hope it is also helpful.