(Cascade)-Delete Directive

I know that this question has come up multiple times now but I want to express the importance of such a feature. Also this thread could be used to track this feature as I think that the other threads rather present workarounds to this currently missing functionality.

Suggested Schema:

directive @delete(soft: Boolean, cascade: Boolean, fields: [String]) on OBJECT | INTERFACE
directive @showDeleted on OBJECT | INTERFACE

type Foo @delete(cascade: true, fields: ["bars"]) {
  bars: [Bar!]
  foobars: [FooBar!]
  a: String!
}

type Bar @delete(soft: true) @showDeleted {
  b: String!
  lols: [Lol!]
}

type FooBar {
   c: String!
}

This schema would generate the following functionality:

  • calling deleteFoo will hard-delete the node itself and all child fields listed using the @cascade directive
  • Bar makes use of the soft-delete flag. On deletion a timestamp deletedAt would be set.
  • queryBar and getBar would default to only retrieve non-deleted nodes but you could opt-in to show also deleted nodes (by providing @showDeleted directive like here)
  • The field lols on type Bar will not get deleted on calling deleteFoo because the cascade flag is not set inside its @delete directive.
  • FooBar is a regular type. Existing behaviour applies.

What do you guys think?

@amaster507 @pawan @rajas

3 Likes

Interesting for sure, but this makes me wonder where the line in the sand is for handling custom business logic. With a dozen developers there could be a dozen tweaks to this depending on the actual needs. So does this get extended to cover all those cases, or is it better for development to push stuff like this somewhere else? (Something like lambda but maybe an actual hook into the go rewriter from GraphQL to DQL—not an official request just me thinking out loud)

I would find such useful and for my use cases I would want to create a directive that normally hides soft deleted nodes and instead of showing them with a filter use something like @showDeleted

@showDeleted would be a natural extension to this feature. I’ll edit my post above to include this.

And regarding specialized business-logic: Maybe the best solution that would cover all these little feature-requests (including this cascade-delete directive) would really be actual pre-/post-hooks written in golang. Maybe it’s just me, but I can’t make friends with the current state of @lambda directives. I still think that something that basic like timestamped soft-delete and cascade-delete should be implemented per default. Every other database has this.

Edit
Although isn’t @showDeleted perfectly handled by @auth currently (given some kind of deletedAt flag)? See my answer in your other thread. Of course having a @showDeleted directive makes this process a lot more transparent and less error-prone.

I wouldn’t use the @showDeleted directive on the schema only on client requests. Just a quick hack that doesn’t require another JWT and doesn’t need to conflict with existing filter logic. Having a complex filter in place it could remain the same with just throwing in this directive as needed.

Again not sure if this is the best way to handle all of these business logic cases. I would be interested to know if other graph databases support features like this from the schema side. Or do they provide any sort of hook like business logic? The main difference is probably going to lead to the fact that they serve servers that create API layers where dgraph removes the need for an API layer and serves clients directly

Sorry, I think I didn’t express myself correct. You wouldn’t need JWT to achieve your requested @showDeleted behaviour right now. Adding @auth(query: {rule: "query {queryFoo(filter: {not: {has: deletedAt}}) {deletedAt}}"}) to your queries (and setting the flag with update) would be sufficient. Of course you could just omit this directive when instead you want to allow queries on deleted objects.

Edit Sorry, I missed the part where you said that you want @showDeleted on client-side. My bad.

I’m also not aware of any graph-databases but I have seen pre- and post-hooks in prisma-nexus (SQL schema → GQL Crud API generation). See: feat: support custom resolvers by craigspaeth · Pull Request #674 · graphql-nexus/nexus-plugin-prisma · GitHub