title: gqlgen coding style code is tightly coupled to neo4j golang
body: <p>I am just starting to get used to gqlgen to create a golang based graphql api for a personal project I am working on.  This is my first attempt at adding a user node into the db, the code works (it took a while, I am new to go neo4j and graphql).</p>
  <p>My problem is it feels very coupled to the db, my coding style would be to abstract away the db operations from this code.  I don't feel sufficiently experienced to achieve this so I am looking for advice to improve before heading into further programming.  I have 25+ years experience of different languages SQL, C++, PHP, Basic, Java, Javascript, Pascal, etc so happy with programming and databases (not so much graph databases).</p>
  <p><strong>Code from schema.resolvers.go</strong></p>
  <pre><code>// UpsertUser adds or updates a user in the system
  func (r *mutationResolver) UpsertUser(ctx context.Context, input model.UserInput) (*model.User, error) {
  
  // Update or insert?
  var userId string
  
  if input.ID != nil {
      userId = *input.ID
  } else {
      newUuid, err := uuid.NewV4() // Create a Version 4 UUID.
      if err != nil {
          return nil, fmt.Errorf(&quot;UUID creation error %v&quot;, err)
      }
      userId = newUuid.String()
  }
  
  // Open session
  session := r.DbDriver.NewSession(neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
  defer func(session neo4j.Session) {
      err := session.Close()
      if err != nil {
  
      }
  }(session)
  
  // Start write data to neo4j
  neo4jWriteResult, neo4jWriteErr := session.WriteTransaction(
      func(transaction neo4j.Transaction) (interface{}, error) {
  
          transactionResult, driverNativeErr :=
              transaction.Run(
                  &quot;MERGE (u:User {uuid: $uuid})  ON CREATE SET u.uuid = $uuid, u.name = $name, u.userType = $userType  ON MATCH SET  u.uuid = $uuid, u.name = $name, u.userType = $userType RETURN u.uuid, u.name, u.userType&quot;,
                  map[string]interface{}{&quot;uuid&quot;: userId, &quot;name&quot;: input.Name, &quot;userType&quot;: input.UserType})
  
          // Raw driver error
          if driverNativeErr != nil {
              return nil, driverNativeErr
          }
  
          // If result returned
          if transactionResult.Next() {
  
              // Return the created nodes data
              return &amp;model.User{
                  ID:       transactionResult.Record().Values[0].(string),
                  Name:     transactionResult.Record().Values[1].(string),
                  UserType: model.UserType(transactionResult.Record().Values[2].(string)),
              }, nil
  
          }
  
          // Node wasn't created there was an error return this
          return nil, transactionResult.Err()
      })
  // End write data to neo4j
  
  //  write failed
  if neo4jWriteErr != nil {
      return nil, neo4jWriteErr
  }
  // write success
  return neo4jWriteResult.(*model.User), nil
  }
  </code></pre>
  <p><strong>Code from resolver.go</strong></p>
  <pre><code>type Resolver struct {
      DbDriver       neo4j.Driver
  }
  </code></pre>
  <p><strong>schema.graphqls</strong></p>
  <pre><code>enum UserType {
    &quot;Administrator account&quot;
    ADMIN
    &quot;Tutor account&quot;
    TUTOR
    &quot;Student account&quot;
    STUDENT
    &quot;Unvalidated Account&quot;
    UNVALIDATED
    &quot;Suspended Account&quot;
    SUSPENDED
    &quot;Retired account&quot;
    RETIRED
    &quot;Scheduled for deletion&quot;
    DELETE
  }
  
  type User {
    id: ID!
    name: String!
    userType: UserType!
  }
  
  input UserInput {
    id: String
    name: String!
    userType: UserType!
  }
  
  type Mutation {
    upsertUser(input: UserInput!) : User!
  }
  </code></pre>