neo4j-graphql-js icon indicating copy to clipboard operation
neo4j-graphql-js copied to clipboard

Error: "Cannot read property '0' of undefined"

Open wilsongp opened this issue 6 years ago • 5 comments

When querying a nested object that's refined in a WITH clause the error is generated with a stack trace like:

TypeError: Cannot read property '0' of undefined
buildCypherSelection ... \\node_modules\\neo4j-graphql-js\\dist\\selections.js:244:20
recurse ... \\node_modules\\neo4j-graphql-js\\dist\\selections.js:73:33
buildCypherSelection ... \\node_modules\\neo4j-graphql-js\\dist\\selections.js:160:12
cypherQuery ... \\node_modules\\neo4j-graphql-js\\dist\\index.js:184:68

which matches to this line

With SDL of:

enum EventType {
  HIT
}
enum Relationship {
  HITTER
}
type StatLeader {
  player: Player
  stat: Int
}
type Query {
  leaders(
    type: EventType!, 
    relationship: Relationship!, 
    first: Int = 3, 
    offset: Int = 0
  ): [StatLeader]
    @cypher( statement: """
      MATCH (e:Event {type: $type})<-[r]-(p:Player) 
      WHERE type(r) = $relationship 
      WITH {player: p, stat: count(e)} as statLeader 
      RETURN statLeader
    """)
}

and query via graphql-playground:

{
  leaders(
    type: HIT, 
    relationship: HITTER, 
    endTimestamp: 1542155521
  ){
    stat,
    player {
      lastName
    },
  }
}

If you don't query the player type field the error isn't thrown

wilsongp avatar Nov 15 '18 01:11 wilsongp

Having the same issue. Any luck getting an explanation or work around ?

willsgh avatar Jan 20 '19 13:01 willsgh

I believe the issue here is the missing @relation directive to specify the relationship between types, specifically connecting StatLeader to Player.

I was able to generate a Cypher query using this slightly modified SDL:

type Player {
  lastName: String
}
enum EventType {
  HIT
}
enum Relationship {
  HITTER
}
type StatLeader {
  name: ID!
  player: Player @relation(name: "IS_PLAYER", direction: "OUT")
  stat: Int
}
type Query {
  leaders(
    type: EventType!, 
    relationship: Relationship!, 
    first: Int = 3, 
    offset: Int = 0
  ): [StatLeader]
    @cypher( statement: """
      MATCH (e:Event {type: $type})<-[r]-(p:Player) 
      WHERE type(r) = $relationship 
      WITH {player: p, stat: count(e)} as statLeader 
      RETURN statLeader
    """)
}

and the GraphQL query:

{
  leaders(
    type: HIT, 
    relationship: HITTER
  ){
    stat,
    player {
      lastName
    },
  }
}

generates this Cypher query:

WITH apoc.cypher.runFirstColumn("MATCH (e:Event {type: $type})<-[r]-(p:Player) 
WHERE type(r) = $relationship 
WITH {player: p, stat: count(e)} as statLeader 
RETURN statLeader", {offset:$offset, first:$first, type:$type, relationship:$relationship}, True) AS x UNWIND x AS `statLeader`
    RETURN `statLeader` { .stat ,player: head([(`statLeader`)-[:`IS_PLAYER`]->(`statLeader_player`:`Player`) | statLeader_player { .lastName }]) } AS `statLeader` SKIP $offset LIMIT $first
{ offset: 0, first: 3, type: 'HIT', relationship: 'HITTER' }

All type references in the SDL should be annotated with the @relation directive. You can see more information about @relation here: https://grandstack.io/docs/neo4j-graphql-js.html#start-with-a-graphql-schema

However, we should do better job of catching this error and providing a more helpful error message, indicating the missing @relation directive.

johnymontana avatar Feb 12 '19 18:02 johnymontana

This would be a good error to catch when implementing #118

johnymontana avatar May 24 '19 00:05 johnymontana

No dice for me.

I don't actually want IS_PLAYER relationships or StatPlayer nodes in my DB as I'm trying to return a dynamic property:

type Project {
    id: ID!
    name: String
}

input LocationInput {
    latitude: Float!
    longitude: Float!
  }

type ProximityResult {
    project: Project
    distance: Float
  }

type Query {
    projectsNearPoint(
      point: LocationInput!
      limit: Int = 20
      searchRadius: Int = 6000
    ): [ProximityResult]
      @cypher(
        statement: """
        WITH point({latitude: $point.latitude, longitude: $point.longitude, crs: 'WGS-84'}) AS here
        MATCH (p:Project)
        WITH round(distance(p.location, here)) as distance, p
        WHERE distance <= (
          CASE
            WHEN $searchRadius <= 10000 THEN $searchRadius
            ELSE 10000 END
        )
        RETURN {
          project: p,
          distance: distance
        }
        ORDER BY distance
        LIMIT (
          CASE
            WHEN $limit <= 30 THEN $limit
            ELSE 30 END
        )
        """
      )
}

I thought I'd be smart be returning a custom ProximityResult type, but for the following query:

{
  projectsNearPoint(point: {
    longitude: 12.4964
    latitude: 41.9028
  }) {
    project {
      name
    }
  }
}

I get a 500 error for my troubles: Expected to find a node at ref slot 1 but found Map{distance -> Double(2.000000e+00), project -> (82409)} instead

mmmoli avatar Aug 05 '19 17:08 mmmoli

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

michaeldgraham avatar May 02 '21 04:05 michaeldgraham