0
votes

I am running a GraphQl mutation via a resolver. Its against a Neo4j database. The query is working fine but I am not able to structure the results in a way that they are displayed back in the result. I've tried several different combinations of results and record mapping but I can't get the properties of the returned result set to show in the outputs.

Specifically, you will see in the below examples that the name field in the response (via GraphiQL) is null when I expect it to be set to the value returned.

Resolver:

 AddIdiomHasChildIdiom(object, params, ctx, resolveInfo) {
      //************************************************************************************************************************************
      //** Author:        MOS
      //** Date:          22/07/2019
      //** Description:   Add a child Idiom         
      //************************************************************************************************************************************

      //Build the cypher query across multiple lines so that we can adjust the query depending on which parameters are passed
      let query = new StringBuilder();

      query.appendLine("MATCH (p:entity:Idiom {id:'" + params.from.id + "'}), (c:entity:Idiom {id:'" + params.to.id + "'})")
      query.appendLine("MERGE (p)-[r:HAS_CHILD_IDIOM]->(c)")
      query.appendLine("RETURN p,c")

      console.log(query)
      //Execute the query and send the results back to the user
      return ctx.driver.session().run(query.toString(), {props:params})
        .then(result => {
          return {
            from: result.records.map(record => { return record.get("p").properties}),
            to: result.records.map(record => { return record.get("c").properties})
          }  
          }) 
        .catch(error => {
          //ToDo: Error handling code need to go here
        })
    }

GraphQL Query

mutation{
  AddIdiomHasChildIdiom(from:{id:"d94676b0-ac6c-11e9-a7a1-edf120d553ac"},to:{id:"e730a720-ac74-11e9-a45f-df629a6df5e1"})
  {
    from{
      name
    }
    to{
      name
    }
  }
}

Output:

{
  "data": {
    "AddIdiomHasChildIdiom": {
      "from": {
        "name": null
      },
      "to": {
        "name": null
      }
    }
  }
}

Relevant Schema Parts

type Mutation{
  AddIdiomHasChildIdiom(
    from: _IdiomInput!
    to: _IdiomInput!
  ): _AddIdiomHasChildIdiomPayload
}

type _AddIdiomHasChildIdiomPayload {
  from: Idiom
  to: Idiom
}
input _IdiomInput {
  id: ID!
}

type _AddIdiomHasChildIdiomPayload {
  from: Idiom
  to: Idiom
}
type Idiom {
    id: ID
    name: String 
    type: IdiomType
    description: String
    lifecycle: IdiomLifecycle
    quality: Float
    numStates: Int
    numChildIdioms: Int
    hasChildIdiom: [Idiom]
    first: Int
    offset: Int
    orderBy: [_IdiomOrdering]
}
1

1 Answers

0
votes

The problem in your code isthat you have mistmatch type between your graphql schema and the implementation of your resolver.

Your mutation query should return this :

type _AddIdiomHasChildIdiomPayload {
  from: Idiom
  to: Idiom
}

And your resolver returns this :

return {
  from: result.records.map(record => { return record.get("p").properties}),
  to: result.records.map(record => { return record.get("c").properties})
}

Here you are using a map function, and its result is an array. So you are returning something like that :

{
  from : [ { id:'', name:'', ... } ]
  to : [ { id:'', name:'', ... } ]
}

And [ { id:'', name:'', ... } ] doesn't validate the Idiom type of your schema, it's an array : Idiom[].

So you need to change your resolver to return just one element for from & to.

And moreover, your implementation is weird : you are doing two loop against the result of Neo4j, due to the use of two map and you don't close the session.

You should try something like that :

const session = ctx.driver.session();
return session.run(query.toString(), {props:params})
  .then(result => {
    return result.records.map(record => {
      return {
        from:record.get("p").properties
        to:record.get("c").properties
      }
    })[0]
  })
  .catch(error => {
      //ToDo: Error handling code need to go here
  })
  .finally(() => {
    session.close();
  })

Moreover