neo4j-graphql / neo4j-graphql-js

NOTE: This project is no longer actively maintained. Please consider using the official Neo4j GraphQL Library (linked in README).
Other
608 stars 148 forks source link

Feature request: Nested mutations #532

Open michaeldgraham opened 3 years ago

michaeldgraham commented 3 years ago

Nested mutations

The next step with the experimental mutation API for nested mutations is to generate relationship field arguments for the data input objects. New input object types would be generated for these, containing nested arguments such as create, connect, update, merge, and delete. The types of these mutation-arguments would also be new input objects, containing the now supported where and / or data arguments.

Given the following schema:

  type User {
    idField: ID! @id
    name: String
    birthday: DateTime
    uniqueString: String! @unique
    indexedInt: Int @index
    rated: [Rating]
  }

  extend type User {
    extensionString: String!
  }

  type Rating @relation(name: "RATING", from: "user", to: "movie") {
    user: User
    rating: Int!
    movie: Movie
  }

  type Movie {
    id: ID! @id
    title: String! @unique
    genre: MovieGenre @index
    ratedBy: [Rating]
  }

  enum MovieGenre {
    Action
    Mystery
    Scary
  }

Experiemntal augmentation results for the nested mutation support of the User node mutation API would be:

  input _UserData {
    idField: ID
    name: String
    birthday: _Neo4jDateTimeInput
    uniqueString: String
    indexedInt: Int
    extensionString: String
    rated: _UserRatedMutation
  }

  input _UserRatedMutation {
    # Create a Movie Node related with a User node for the RATING relationship
    create: [_CreateUserRatedMovie]
    # connect: ...
  }

  input _CreateUserRatedMovie {
    # require the .rating relationship property because it is non-null on Rating
    rating: Int!
    # require providing data for the Movie to be created and related with a User
    movie: _MovieData!
  }

  input _MovieData {
    title: String!
    ratedBy: _MovieRatedByMutation
  }

  # ...

The translation process would pick these arguments up and recursively generate a Cypher operation composed of Cypher subqueries, to be executed before the generated Cypher for the RETURN statement corresponding to the mutation's GraphQL selection set.

mutation {
  CreateUser(
    data: {
      name: "Michael",
      # new relationship input field
      rated: {
        # create a Movie node and add a relationship with it
        create: {
          rating: 10,
          movie: {
            title: "The Matrix"
          }
        }
      }
    }
  ) {
    # selection set
    name
    rated {
      rating
      movie {
        title
      }
    }
  }
}

Nested mutation input fields

For the input objects generated for relationship field arguments to be added to node mutations:

Node

Relationship

Possible nested sequences

The following minimal nested combinations would be possible to generate. Any more complex pattern would be composed of pairs of these combinations. Moving forward, each combination needs to be assessed to identify requirements and strategies for translation. Custom errors may be useful / necessary for patterns that don't make sense under certain conditions.

So starting off, one might...

This feature request will be progressively updated with more implementation details regarding generated input types and custom error scenarios.

This feature request is relevant to #89 and #331.

michaeldgraham commented 3 years ago

https://github.com/neo4j-graphql/neo4j-graphql-js/issues/608 ;)