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

how to deal with (A1)-[r1]-(B)-[r2]-(A1) path style

Open rashad-mohamed-gehan opened this issue 7 years ago • 8 comments

data

Ahmed -:Love-> Sara 
Sara -:Hate->  Ahmed
Sara -:Hate->  Ali
-----------
schema

type Boy{
name: String
LoveGirl:Girl
}
type Girl{
name: String
HateBoy:Boy
}
-----------------
query GetBoy($name: String) {
Boy{
name
LoveGirl{
name
HateBoy{
name
}
}
}
}


result Ahmed -:Love-> Sara -:Hate-> Ahmed ////// expected Ahmed -:Love-> Sara -:Hate-> Ali ////// not expected

how i solve it:

type Boy{
name: String
LoveGirl:Girl
}
type Girl{
name: String
HateBoy:Boy @cypher(statement: "MATCH (this)<-[:Hate]-(B:Boy) where B.name=$name  RETURN B")
}

```---------------------------
result 
Ahmed -:Love-> Sara -:Hate->  Ahmed ////// expected
------------------------------------------------------------------
my question:
 is my solution is best practices or there is another one? if there please tell me?
thanks.

rashad-mohamed-gehan avatar Jan 14 '19 11:01 rashad-mohamed-gehan

@jexp could you please help me! cause my own solution does not work well.

rashad-mohamed-gehan avatar Jan 15 '19 13:01 rashad-mohamed-gehan

What doesn't work well with your solution? (You missed the name parameter in HateBoy)

You could also navigate along the relationship with a filter.

query {
   Boy(name:"Ahmed") {
     name
     LoveGirl(name:"Sara") {
        name
        HateBoy(filter: { HateBoy_name: "Ahmed"}) {
          name
       }
}

jexp avatar Jan 16 '19 03:01 jexp

is that mean another hit on database required to filter boys and get boy with name "Ahmed"?

if so? why i have to duplicate filtering in database? what about refering to Boy node i have got before which is "Ahmed"?


what does not working well is passing parameters :

  Organization(orgId: $orgId, first: 1) {
    name
    employees {
      first_name
      last_name
      salary(orgId: $orgId) {
        gross
      }
    }
  }
}

parameters: {"orgId":"12345678945679532"}

schema

orgId: String
name: String
employees : [Employee]
}

type Employee{
 first_name: String
 last_name: String
Salary(orgId: String): Salary @cypher(statement: "MATCH (this)-[:HAS_SALARY]->(S:Salary)<-[:HAS_EMPLOYEE_SALARY]-(O:Organization) where O.orgId=$orgId RETURN distinct S") 
}

type Salary{
gross
}

result organization returned successfully employee returned successfully Salary is null //not expected


trying to print orgId inside employee

 first_name(orgId: String): String @cypher(statement: "RETURN $orgId ") 
 last_name: String
Salary(orgId: String): Salary @cypher(statement: "MATCH (this)-[:HAS_SALARY]->(S:Salary)<-[:HAS_EMPLOYEE_SALARY]-(O:Organization) where O.orgId=$orgId RETURN distinct S") 
}

updated query 
query GetOrganizations($orgId: String) {
  Organization(orgId: $orgId, first: 1) {
    name
    employees {
      first_name(orgId: $orgId)
      last_name
      salary(orgId: $orgId) {
        gross
      }
    }
  }
}

it print in first_name {'orgId'} not "12345678945679532" value as expected

rashad-mohamed-gehan avatar Jan 16 '19 08:01 rashad-mohamed-gehan

Can you please try to use proper Markdown formatting for code in your issues? This makes it really hard to read them!

jexp avatar Jan 16 '19 09:01 jexp

@jexp updated :)

rashad-mohamed-gehan avatar Jan 16 '19 10:01 rashad-mohamed-gehan

Lots of different questions. Perhaps you could split them into different issues.

  1. graphql doesn't allow to refer to previous nodes higher up the tree
  2. you're not filtering twice, you pass the name filter for the boy only once
  3. the querying for the $orgId should work for salray, and also for the "first_name"

I'd have to turn your cases into unit tests to see what the issue is. But if you have already the employee. does he have multiple organizations?

I guess you could also use filters to restrict the ORG for the salary.

jexp avatar Jan 16 '19 11:01 jexp

First, sorry for a bad representation and different questions :) that's because work hours, and i have to represent identical sample because the data is very confidential. thanks by the way for your help.

yup employee may have multiple organizations.

the parameters work fine, but when replacing $orgId string with hard coded value "12345678978522454"

  Organization(orgId: "12345678978522454", first: 1) {
    name
    employees {
      first_name(orgId: "12345678978522454")
      last_name
      salary(orgId:  "12345678978522454") {
        gross
      }
    }
}

rashad-mohamed-gehan avatar Jan 16 '19 11:01 rashad-mohamed-gehan

What happens then?

I tried to reproduce your issue with a test but couldn't see the problem:

    @Test
    fun dynamicFieldArgParameter() {
        val schema = """
        type Person {
           name: String
           arg(foo:String): String @cypher(statement:"return {foo}")
        }
        """

        GraphSchemaScanner.storeIdl(db!!, schema)
        val graphQL = GraphSchema.getGraphQL(db!!)
        val result = graphQL.execute("query(\$a:String) { Person { name, arg(foo:\$a) }}", GraphQLContext(db!!,parameters = mapOf("a" to "Joe")))
        println(result)
        assertEquals(mapOf("Person" to listOf(mapOf("name" to "Jane","arg" to "Joe"),mapOf("name" to "John","arg" to "Joe"))),result.getData())
    }

jexp avatar Jun 19 '19 17:06 jexp