neo4j / graphql

A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations.
https://neo4j.com/docs/graphql-manual/current/
Apache License 2.0
508 stars 149 forks source link

where condition is not applying on interface field Unknown argument where on field #2642

Closed Hashdhi closed 1 year ago

Hashdhi commented 1 year ago

Schema

interface Production {
    title: String!
    actors: [Actor!]!
    distribution:[DistributionHouse!]!
}

type Movie implements Production @node(label:"Film"){
    title: String!
    actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN, properties: "ActedIn")
    runtime: Int!
    distribution:[DistributionHouse!]! @relationship(type: "DISTRIBUTED_BY", direction: IN)
}

type Series implements Production {
    title: String!
    actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN, properties: "ActedIn")
    episodes: Int!
    distribution:[DistributionHouse!]! @relationship(type: "DISTRIBUTED_BY", direction: IN)
}

interface ActedIn @relationshipProperties {
    role: String!
}

type Actor {
    name: String!
    actedIn: [Production!]! @relationship(type: "ACTED_IN", direction: OUT, properties: "ActedIn")
}

interface DistributionHouse{
    name:String!
}

type Dishney implements DistributionHouse{
      name:String!
      review:String!
}

Production and Distribution is interface

query GetDistributionName {
 actors {
   actedIn (where: { _on: { Movie: {} } }){
      title
      distribution(where: { _on: { Dishney: {} } }){
          name
      }
   }
 } 
}

Below is the error

"message": "Unknown argument \"where\" on field \"Production.distribution\".", "extensions": { "code": "GRAPHQL_VALIDATION_FAILED",

query GetDistributionName {
 actors {
   actedIn (where: { _on: { Movie: {} } }){
      title
      distribution(where: {name: "Prime"}){
          name
      }
   }
 } 
}

"message": "Unknown argument \"where\" on field \"Production.distribution\".", "extensions": { "code": "GRAPHQL_VALIDATION_FAILED",

tbwiss commented 1 year ago

Hi @Hashdhi: To be honest, I'm not sure if this is a bug or if it simply hasn't been implemented yet.

As a ”workaround”, the only thing that may help is something along the line of this:

query GetDistributionName {
  actors {
    actedIn(where: { _on: { Movie: {} } }) {
      title
      ... on Movie {
        distribution(where: { _on: { Dishney: {} } }) {
          name
        }
      }
    }
  }
}
Hashdhi commented 1 year ago

Hi @tbwiss Thanks for the workaround . However its not working as expected ,union query is getting generated and adds where condition to all the types which is implementing the DistributionHouse interface.

There is a another issue had created which might be related reference : https://github.com/neo4j/graphql/issues/2566

Actually in our model a plenty(~75) of types implementing common interface hence very big query is getting generated which lead lots of perf overhead .

interface Production {
    title: String!
    actors: [Actor!]!
    distribution:[DistributionHouse!]!
}

type Movie implements Production @node(label:"Film"){
    title: String!
    actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN, properties: "ActedIn")
    runtime: Int!
    distribution:[DistributionHouse!]! @relationship(type: "DISTRIBUTED_BY", direction: IN)
}

type Series implements Production {
    title: String!
    actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN, properties: "ActedIn")
    episodes: Int!
    distribution:[DistributionHouse!]! @relationship(type: "DISTRIBUTED_BY", direction: IN)
}

interface ActedIn @relationshipProperties {
    role: String!
}

type Actor {
    name: String!
    actedIn: [Production!]! @relationship(type: "ACTED_IN", direction: OUT, properties: "ActedIn")
}

interface DistributionHouse{
    name:String!
}

type Dishney implements DistributionHouse{
      name:String!
      review:String!
}

type Prime implements DistributionHouse{
      name:String!
      review:String!
}

type Netflix implements DistributionHouse{
      name:String!
      review:String!
}

Generated Cypher [UNION Query for all the types and where condition]

MATCH (this:`Actor`)

WITH *
CALL {
WITH *
CALL {
    WITH this
    MATCH (this)-[this0:ACTED_IN]->(this_Movie:`Film`)
    WITH *
    CALL {
    WITH *
    CALL {
        WITH this_Movie
        MATCH (this_Movie)<-[this1:DISTRIBUTED_BY]-(this_Movie_Dishney:`Dishney`)
        WHERE this_Movie_Dishney.name = $param0

        RETURN { __resolveType: "Dishney", name: this_Movie_Dishney.name } AS this_Movie_distribution
        UNION
        WITH this_Movie
        MATCH (this_Movie)<-[this2:DISTRIBUTED_BY]-(this_Movie_Prime:`Prime`)
        WHERE this_Movie_Prime.name = $param1

        RETURN { __resolveType: "Prime", name: this_Movie_Prime.name } AS this_Movie_distribution
        UNION
        WITH this_Movie
        MATCH (this_Movie)<-[this3:DISTRIBUTED_BY]-(this_Movie_Netflix:`Netflix`)
        WHERE this_Movie_Netflix.name = $param2

        RETURN { __resolveType: "Netflix", name: this_Movie_Netflix.name } AS this_Movie_distribution
    }
    RETURN collect(this_Movie_distribution) AS this_Movie_distribution
    }
    RETURN { __resolveType: "Movie", distribution: this_Movie_distribution, title: this_Movie.title } AS this_actedIn
}
RETURN collect(this_actedIn) AS this_actedIn
}
RETURN this { actedIn: this_actedIn }
tbwiss commented 1 year ago

@Hashdhi indeed. Yes, I see now that this has been raised before in https://github.com/neo4j/graphql/issues/810. We added this to the Abstract types 2.0 milestone. At the moment I'm afraid that I can't give you an estimate on when this will be addressed.

Liam-Doodson commented 1 year ago

Hi @Hashdhi, I just took a quick look at your type definitions and noticed that you are missing a @relationship directive from the Production type. If you modify the type definition to the following you should no longer see the error:

interface Production {
  title: String!
  actors: [Actor!]!
  distribution: [DistributionHouse!]! @relationship(type: "DISTRIBUTED_BY", direction: IN)
}