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

Incorrect results when using cypher directive on field returning relationship type

Open danielmcmillan opened this issue 5 years ago • 3 comments

When custom Cypher is used for a field returning a relationship type, incorrect results are returned for node fields on the result. The properties on the relationship are correct, but the same, incorrect node is returned for every relationship.

This is what I think is going on: In directedNodeTypeFieldOnRelationType, '_relation' is added to the end of variable name. In customCypherField, '_relation' is not being appended to nestedVariable. Therefore the selection for the directed node will use an unbound name for the relation, so it matches every existing relationship.

danielmcmillan avatar Mar 01 '19 00:03 danielmcmillan

Hey @danielmcmillan, could you show me an example of how you're trying to use a @cypher directive on a field returning a relationship type? What are you wanting to return from its Cypher statement?

Are you doing something like this?

type NodeA {
  relationshipTypeField: [RelationshipAB] @cypher(statement: "...")
}

type RelationshipAB {
  from: NodeA
  ...
  to: NodeB
}

type NodeB {
  ...
}

The GraphQL to Cypher translation processes that support using relationship types don't currently manage for the possibility of fields returning relationship types also having @cypher directives on them. In a way, this would be like using a @cypher directive on a field that already has a @relation directive. Because of the@relation directive, the field would already obtain translation support for being a relationship in Neo4j.

However, @cypher directives can be used on relationship type fields. Do you think there might be a way to model your needs using something like:

type NodeA {
  relationshipField: [RelationshipAB]
}

type RelationshipAB {
   from: NodeA
   computedField: String @cypher(statement: "")
   to: NodeB
}

type NodeB {
  ...
}

michaeldgraham avatar Mar 01 '19 02:03 michaeldgraham

Thanks @michaeldgraham, The @cypher directive is being used to filter the returned relationships by a field on a third node.

Something like this:

type NodeA {
  relationshipTypeField(cId: String): [RelationshipAB]
    @cypher(statement: "MATCH (this)-[r:RELATED_TO]-(:NodeB)-[]-(:NodeC {id: $cId}) RETURN r;")
}

type RelationshipAB @relation(name: "RELATED_TO") {
  from: NodeA
  ...
  to: NodeB
}

type NodeB {
  relatedC: NodeC @relation(...)
  ...
}

type NodeC {
  id: String
  ...
}

So then if I run this query:

query {
  NodeA {
    relationshipTypeField(cId: "x") {
      NodeB {
        relatedC {
          id
        }
      }
    }
  }
}

Only relationships where NodeB->relatedC->id is "x" will be returned. The reason for the query is that NodeC represents a category, and NodeB is assigned to a category. We want to retrieve B by category from node A.

Thanks for the explanation, helps to understand why I should expect strange behaviour in this case. Since I am filtering the list of returned relationships I don't think a computed field on the relationship type will help. I'd be happy to hear if there is any better/alternate way to model cases like this though.

danielmcmillan avatar Mar 01 '19 03:03 danielmcmillan

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

michaeldgraham avatar May 02 '21 04:05 michaeldgraham