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
609 stars 147 forks source link

Input type parameter not passed to custom Cypher query #192

Closed johnymontana closed 5 years ago

johnymontana commented 5 years ago

I've defined a custom mutation field MergeStory with a @cypher directive that takes a StoryInput. I expect the input object data to be passed to the Cypher sub-query as a parameter, however it is not included.

Partial typedefs:

type Story {
    id: ID!
    descendants: Int @cypher(statement: "")
    score: Int
    time: DateTime
    title: String
    url: String
    comments: [Comment] @relation(name: "HAS_COMMENT", direction: "OUT")
    by: User @relation(name: "SUBMITTED", direction: "IN")
}

input StoryInput {
    by: String
    id: ID!
    kids: [ID!]
    timeinput: String
    title: String
    url: String 
}

type Mutation {
    MergeStory(data: StoryInput): Story @cypher(statement: """ 
        MERGE (s:Story {id: $data.id})
        SET s.time = DateTime({formatted: $data.timeinput}),
            s.score = $data.score,
            s.title = $data.title,
            s.url   = $data.url
        MERGE (u:User {id: $data.by})
        MERGE (u)-[:SUBMITTED]->(s)
        RETURN s       
    """
    )

    MergeComment(data: CommentInput): Comment @cypher(statement: """

    )
}

Given this GraphQL query:

mutation mergeStory($data: StoryInput) {
  MergeStory(data: $data) {
    id
  }
}

{
    "data": 
    { "by": "ryan_j_naughton",
      "descendants": 0,
      "id": 19122525,
      "score": 1,
      "time": 1549723769,
      "title": "Uber\'s bike service is cutting into car rides",
       "type": "story",
      "url":
   "https://www.engadget.com/2019/02/08/uber-jump-bikes-lead-to-fewer-car-rides/" }
}

This is the generated Cypher query:

CALL apoc.cypher.doIt("MERGE (s:Story {id: $data.id})
SET s.time = DateTime({formatted: $data.timeinput}),
    s.score = $data.score,
    s.title = $data.title,
    s.url   = $data.url
MERGE (u:User {id: $data.by})
MERGE (u)-[:SUBMITTED]->(s)
RETURN s       ", {first:$first, offset:$offset}) YIELD value
    WITH apoc.map.values(value, [keys(value)[0]])[0] AS `story`
    RETURN `story` { .id } AS `story` SKIP $offset
{ first: -1, offset: 0 }

Expect data object argument to be included in apoc.cypher.doIt call, but only first and offset are included.

If I flatten the MergeStory mutation params (no input type) then it works as expected:

MergeStoryFlat(by: String, id: ID!, kids: [ID!], timeinput: String, title: String, url: String): Story @cypher(statement: """
    MERGE (s:Story {id: $id})
        SET 
            s.title = $title,
            s.url   = $url
        MERGE (u:User {id: $by})
        MERGE (u)-[:SUBMITTED]->(s)
        RETURN s     
    """

results in:

CALL apoc.cypher.doIt("MERGE (s:Story {id: $id})
    SET 
        s.title = $title,
        s.url   = $url
    MERGE (u:User {id: $by})
    MERGE (u)-[:SUBMITTED]->(s)
    RETURN s     ", {by:$by, id:$id, title:$title, url:$url, first:$first, offset:$offset}) YIELD value
    WITH apoc.map.values(value, [keys(value)[0]])[0] AS `story`
    RETURN `story` { .id } AS `story` SKIP $offset
{ by: 'ryan_j_naughton',
  id: '19122525',
  title: 'Ubers bike service is cutting into car rides',
  url:
   'https://www.engadget.com/2019/02/08/uber-jump-bikes-lead-to-fewer-car-rides/',
  first: -1,
  offset: 0 }
johnymontana commented 5 years ago

Fixed in #200