Reputation: 27
I have a set of nodes labeled as Person and City. Node citiy has two properties Name and isInAustralia. A person can have relation 'hasHouse' relationship with the City node. A person can have multiple houses
I want to retrieve the data in such a way that it results in format: Name of the person || CityInAustralia ||CityOutsideAustralia
suppose a person has a house in city A,D,E in the Australia and houses in city B,C outside the Australia.
The result I am getting is :
Adam----A----B
Adam----D-----B
Adam----E----B
Adam----A-----C
Adam----D----C
Adam----E-----C
I have tried the below written query:
Match(person:Person{Name:"Adam"})-[rel:hasHouseIn]->(city:City)
where city.isInAustralia="true"
optional match (person:Person{Name:"Adam"})-[rel:hasHouseIn]->
(cityOutside:City)
where city.isInAustralia="false"
return person.Name,City.Name as CityInAustralia ,cityOutside.Name as
CityOutsideAustralia
I want results to be like:
Name ---------- CityInAustralia ---------- CityOutsideAustralia
Adam------------A-----------------------------B
Adam------------D-------------------------C
Adam------------E-------------------------Blank
I want to get a result as what we get when we apply left outer join in sql sever where Name will be the column on which we will join.
Upvotes: 0
Views: 112
Reputation: 6270
I don't really know exactly what you're trying to do - the query won't work as it is as you have duplicate identifiers (rel
) so you'd get nothing as a result. But also - if you have 'Adam' having 3 houses (A,D,E) in Australia, and 2 outside (B,C), you'll get:
A --> B
A --> C
D --> B
D --> C
E --> B
E --> C
Neo4j can't determine which of the cityOutside
should be displayed with cityInAustralia
as that would have to be a random guess, that seems like a post processing job. The query that will get you the results I've indicated above is:
MATCH (person:Person{Name:"Adam"})-[:hasHouseIn]->(city:City {IsInAustralia:true})
OPTIONAL MATCH (person)-[:hasHouseIn]->(cityOutside:City {IsInAustralia:false})
RETURN
person.Name,
city.Name AS CityInAustralia,
cityOutside.Name AS CityOutsideAustralia
Personally, I would use Collect
and get two arrays so you get:
CityInsideAustralia: [A,D,E],
CityOutsideAustralia: [B,C]
So you only get one result per Person
:
MATCH (person:Person{Name:"Adam"})-[:hasHouseIn]->(city:City {IsInAustralia:true})
OPTIONAL MATCH (person)-[:hasHouseIn]->(cityOutside:City {IsInAustralia:false})
RETURN
person.Name,
COLLECT(DISTINCT city.Name) AS CityInAustralia,
COLLECT(DISTINCT cityOutside.Name) AS CityOutsideAustralia
NB. I'm using the below dataset:
CREATE
(p:Person {Name:'Adam'})-[:hasHouseIn]->(:City {IsInAustralia:true, Name:'A'}),
(p)-[:hasHouseIn]->(:City {IsInAustralia:true, Name:'D'}),
(p)-[:hasHouseIn]->(:City {IsInAustralia:true, Name:'E'}),
(p)-[:hasHouseIn]->(:City {IsInAustralia:false, Name:'B'}),
(p)-[:hasHouseIn]->(:City {IsInAustralia:false, Name:'C'})
Upvotes: 2