Skip to content

Commit 710a9a2

Browse files
committed
add optional match for 1..1 relations
1 parent e57cb1a commit 710a9a2

File tree

6 files changed

+78
-24
lines changed

6 files changed

+78
-24
lines changed

core/src/main/kotlin/org/neo4j/graphql/handler/projection/ProjectionBase.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -570,10 +570,14 @@ open class ProjectionBase(
570570
relationship = relationship.named(childVariableName)
571571
}
572572

573+
val with = with(variable)
573574
val where = where(anyNode(childVariableName), fieldDefinition, nodeType, field, env.variables)
574-
var reading: OngoingReading = with(variable)
575-
.match(relationship)
576-
.where(where)
575+
576+
var reading: OngoingReading = when {
577+
fieldDefinition.type.isList() -> with.match(relationship)
578+
else -> with.optionalMatch(relationship)
579+
}.where(where)
580+
577581
val subQuery = if (fieldDefinition.type.isList()) {
578582
val ordering = orderBy(childVariableName, field.arguments, fieldDefinition, env.variables)
579583
val skipLimit = SkipLimit(childVariable, field.arguments, fieldDefinition)

core/src/test/resources/movie-tests.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ MATCH (movieById:Movie)
256256
WHERE movieById.movieId = $movieByIdMovieId
257257
CALL {
258258
WITH movieById
259-
MATCH (movieById)-[:FILMED_IN]->(movieByIdFilmedIn:State)
259+
OPTIONAL MATCH (movieById)-[:FILMED_IN]->(movieByIdFilmedIn:State)
260260
RETURN movieByIdFilmedIn {
261261
.name
262262
} AS movieByIdFilmedIn LIMIT 1
@@ -310,7 +310,7 @@ CALL {
310310
}
311311
CALL {
312312
WITH movieById
313-
MATCH (movieById)-[:FILMED_IN]->(movieByIdFilmedIn:State)
313+
OPTIONAL MATCH (movieById)-[:FILMED_IN]->(movieByIdFilmedIn:State)
314314
RETURN movieByIdFilmedIn {
315315
.name
316316
} AS movieByIdFilmedIn LIMIT 1

core/src/test/resources/relationship-tests.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ RETURN category {
642642
MATCH (category:Category)
643643
CALL {
644644
WITH category
645-
MATCH (category)-[:HAS_PARENT]->(categoryParentCategory:Category)
645+
OPTIONAL MATCH (category)-[:HAS_PARENT]->(categoryParentCategory:Category)
646646
RETURN categoryParentCategory {
647647
.name
648648
} AS categoryParentCategory LIMIT 1
@@ -723,7 +723,7 @@ RETURN category {
723723
MATCH (category:Category)
724724
CALL {
725725
WITH category
726-
MATCH (category)-[categoryParentCategoryAssignment:HAS_PARENT]->(categoryParentCategoryAssignmentParent:Category)
726+
OPTIONAL MATCH (category)-[categoryParentCategoryAssignment:HAS_PARENT]->(categoryParentCategoryAssignmentParent:Category)
727727
RETURN categoryParentCategoryAssignment {
728728
parent: categoryParentCategoryAssignmentParent {
729729
.name

core/src/test/resources/translator-tests1.adoc

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ MATCH (person:Person) RETURN person { .age } AS person ORDER BY person.name ASC
9292
MATCH (person:Person)
9393
CALL {
9494
WITH person
95-
MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
95+
OPTIONAL MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
9696
RETURN personBorn {
9797
.date,
9898
to: personBornTo {
@@ -240,7 +240,7 @@ RETURN person {
240240
MATCH (person:Person)
241241
CALL {
242242
WITH person
243-
MATCH (person)-[:LIVES_IN]->(personLivesIn:Location)
243+
OPTIONAL MATCH (person)-[:LIVES_IN]->(personLivesIn:Location)
244244
RETURN personLivesIn {
245245
.name
246246
} AS personLivesIn LIMIT 1
@@ -316,7 +316,7 @@ MATCH (person:Person) RETURN person { .name } AS person
316316
MATCH (person:Person)
317317
CALL {
318318
WITH person
319-
MATCH (person)-[personDied:DIED]->(personDiedWhere:Location)
319+
OPTIONAL MATCH (person)-[personDied:DIED]->(personDiedWhere:Location)
320320
RETURN personDied {
321321
.date,
322322
where: personDiedWhere {
@@ -350,10 +350,10 @@ RETURN person {
350350
MATCH (person:Person)
351351
CALL {
352352
WITH person
353-
MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
353+
OPTIONAL MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
354354
CALL {
355355
WITH personBornTo
356-
MATCH (personBornTo)<-[:FOUNDED]-(personBornToFounded:Person)
356+
OPTIONAL MATCH (personBornTo)<-[:FOUNDED]-(personBornToFounded:Person)
357357
RETURN personBornToFounded {
358358
.name
359359
} AS personBornToFounded LIMIT 1
@@ -392,13 +392,13 @@ RETURN person {
392392
MATCH (person:Person)
393393
CALL {
394394
WITH person
395-
MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
395+
OPTIONAL MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
396396
CALL {
397397
WITH personBornTo
398-
MATCH (personBornTo)<-[:FOUNDED]-(personBornToFounded:Person)
398+
OPTIONAL MATCH (personBornTo)<-[:FOUNDED]-(personBornToFounded:Person)
399399
CALL {
400400
WITH personBornToFounded
401-
MATCH (personBornToFounded)-[personBornToFoundedBorn:BORN]->(personBornToFoundedBornTo:Location)
401+
OPTIONAL MATCH (personBornToFounded)-[personBornToFoundedBorn:BORN]->(personBornToFoundedBornTo:Location)
402402
RETURN personBornToFoundedBorn {
403403
.date,
404404
to: personBornToFoundedBornTo {
@@ -447,7 +447,7 @@ RETURN person {
447447
MATCH (person:Person)
448448
CALL {
449449
WITH person
450-
MATCH (person)-[:LIVES_IN]->(personLivesIn:Location)
450+
OPTIONAL MATCH (person)-[:LIVES_IN]->(personLivesIn:Location)
451451
WHERE personLivesIn.name = $personLivesInName
452452
RETURN personLivesIn {
453453
.name
@@ -682,10 +682,10 @@ RETURN person {
682682
MATCH (person:Person)
683683
CALL {
684684
WITH person
685-
MATCH (person)-[:LIVES_IN]->(personLivesIn:Location)
685+
OPTIONAL MATCH (person)-[:LIVES_IN]->(personLivesIn:Location)
686686
CALL {
687687
WITH personLivesIn
688-
MATCH (personLivesIn)<-[:FOUNDED]-(personLivesInFounded:Person)
688+
OPTIONAL MATCH (personLivesIn)<-[:FOUNDED]-(personLivesInFounded:Person)
689689
RETURN personLivesInFounded {
690690
.name
691691
} AS personLivesInFounded LIMIT 1
@@ -838,7 +838,7 @@ RETURN location {
838838
MATCH (person:Person)
839839
CALL {
840840
WITH person
841-
MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
841+
OPTIONAL MATCH (person)-[personBorn:BORN]->(personBornTo:Location)
842842
RETURN personBorn {
843843
__typename: 'Birth'
844844
} AS personBorn LIMIT 1

core/src/test/resources/translator-tests2.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ MATCH (user:User)
4747
WHERE user.name = $userName
4848
CALL {
4949
WITH user
50-
MATCH (user)-[userReferredBy:REFERRED_BY]->(userReferredByReferredBy:User)
50+
OPTIONAL MATCH (user)-[userReferredBy:REFERRED_BY]->(userReferredByReferredBy:User)
5151
RETURN userReferredBy {
5252
.referralDate,
5353
referredBy: userReferredByReferredBy {

core/src/test/resources/translator-tests3.adoc

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,86 @@ type Referral @relation (name:"REFERRED_BY", from:"referredBy", to: "user", dire
1818
}
1919
----
2020

21+
== Test Data
22+
23+
[source,cypher,test-data=true]
24+
----
25+
CREATE
26+
(u1:User {name: 'Max'}),
27+
(u2:User {name: 'Marie'}),
28+
(u3:User {name: 'Thomas'}),
29+
(u4:User {name: 'Jane'}),
30+
(u1)-[:REFERRED_BY{referralDate: "2021-01-01"}]->(u3),
31+
(u2)-[:REFERRED_BY{referralDate: "2021-01-02"}]->(u3),
32+
(u3)-[:REFERRED_BY{referralDate: "2021-01-03"}]->(u4)
33+
----
34+
2135
== Tests
2236

2337
=== relation with same types changed direction
2438

2539
.GraphQL-Query
2640
[source,graphql]
2741
----
28-
{user(name:"Jane") {
42+
{user( filter: {name_in: ["Jane", "Thomas"]}) {
2943
name
3044
referredBy { referralDate referredBy {name} }
3145
referred { referralDate user {name} }
3246
} }
3347
----
3448

49+
.GraphQL-Response
50+
[source,json,response=true]
51+
----
52+
{
53+
"user" : [ {
54+
"name" : "Thomas",
55+
"referredBy" : {
56+
"referralDate" : "2021-01-03",
57+
"referredBy" : {
58+
"name" : "Jane"
59+
}
60+
},
61+
"referred" : [ {
62+
"referralDate" : "2021-01-02",
63+
"user" : {
64+
"name" : "Marie"
65+
}
66+
}, {
67+
"referralDate" : "2021-01-01",
68+
"user" : {
69+
"name" : "Max"
70+
}
71+
} ]
72+
}, {
73+
"name" : "Jane",
74+
"referredBy" : null,
75+
"referred" : [ {
76+
"referralDate" : "2021-01-03",
77+
"user" : {
78+
"name" : "Thomas"
79+
}
80+
} ]
81+
} ]
82+
}
83+
----
84+
3585
.Cypher params
3686
[source,json]
3787
----
3888
{
39-
"userName" : "Jane"
89+
"filterUserNameIn" : [ "Jane", "Thomas" ]
4090
}
4191
----
4292

4393
.Cypher
4494
[source,cypher]
4595
----
4696
MATCH (user:User)
47-
WHERE user.name = $userName
97+
WHERE user.name IN $filterUserNameIn
4898
CALL {
4999
WITH user
50-
MATCH (user)-[userReferredBy:REFERRED_BY]->(userReferredByReferredBy:User)
100+
OPTIONAL MATCH (user)-[userReferredBy:REFERRED_BY]->(userReferredByReferredBy:User)
51101
RETURN userReferredBy {
52102
.referralDate,
53103
referredBy: userReferredByReferredBy {

0 commit comments

Comments
 (0)