Delta
Delta

Reputation: 2022

Cypher query to get node and subnodes like a single object with arrays

I have this json:

{
    "name":"david", //node:Person
    "TAKING":[ //link
        {"name":"math"}, //node:Subject
        {"name":"physics"} //node:Subject
    ],
    "FRIEND":[ //link
        {"name":"andres"}, //node:Person
        {"name":"luis"} //node:Person
    ]
}

And I have this query to extract it from neo4j

start person=node(*) match person-[:FRIEND]->friend, person-[:TAKING]->subject where person.name="Andres" return person, collect(distinct friend), collect(distinct subject);

The result is this:

==> +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
==> | person                                   | collect(distinct friend)                                                         | collect(distinct subject)                      |
==> +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
==> | Node[1]{name:"Andres",title:"Developer"} | [Node[2]{name:"David",title:"Developer"},Node[3]{name:"Luis",title:"Developer"}] | [Node[5]{name:"math"},Node[6]{name:"physics"}] |
==> +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

I think this part of the query can be better:

person-[:FRIEND]->friend, person-[:TAKING]->subject

The goal is to avoid the distinc clause in the return part:

collect(distinct friend), collect(distinct subject)

I rewrite it to:

subject<-[:TAKING]-person-[:FRIEND]->friend

but same result.

Is there a better way to make this query?, and Is there a way to build the original json with cypher?

Upvotes: 1

Views: 501

Answers (1)

Henrik Sachse
Henrik Sachse

Reputation: 54182

Try the following query as demonstrated in http://console.neo4j.org/?id=mlwmlt to avoid the DISTINCT keyword:

START person=node(*) 
WHERE HAS (person.name) AND person.name='A' 
WITH person 
MATCH (subject)<-[:TAKING]-(person) 
WITH person, COLLECT(subject) AS subjects 
MATCH (person)-[:FRIEND]->(friend) 
RETURN person, subjects, COLLECT(friend)

But in general you should not use node(*). A good idea would be using an index of names instead.

Upvotes: 1

Related Questions