简体   繁体   中英

Neo4j cypher query collect in collect

I have a query:

start brand=node(62) match  brand-[:CREATED_A]->(campaign:Campaign)<-->(node) 
return DISTINCT  brand,campaign,collect(node) ;

Right now the results coming back almost as I wanted. The one thing that I'm missing is that I want to have a hierarchy of the following:

brand has a lot of campaigns and campaigns has a lot of node connected to it so kind of nodes in campaign in brand.

Right now the campaign is coming back multiple time to each campaign that is returning.

I have provided a Neo4j Gist that illustrates a solution. In short it uses literal maps to format the data and two collects to make sure that the brands does not occur multiple times.

MATCH 
    (brand:Brand)-[:CREATED_A]->(campaign:Campaign)<-->(node)
WITH 
    brand, 
    { 
        campaign : campaign, 
        nodes : COLLECT(node)
    } AS campaigns
WITH 
    { 
        brand : brand, 
        campaigns : COLLECT(campaigns)
    } AS brands
RETURN brands

This makes the brands occur once and you get a nice format for your output.

Cypher is a very powerful language. If you know which properties you want to get from the nodes you can even return a json-like output that maintains also the structure you actually modelled in your graph, you can do something like this:

MATCH (brand:Brand)-[:CREATED_A]->(campaign:Campaign)<-->(node)
WITH 
    brand, 
    campaign as campaign,
    COLLECT({
         property1 : node.property1,
         property2 : node.property2
    }) as nodes
RETURN 
    { 
        name : brand.name,
        logoUrl : brand.logoUrl,
        campaigns : COLLECT({
            name : campaign.name,
            timestamp : campaign.timestamp,
            nodes : nodes
        })
    } as brands

this will output a json structure such as:

[
    {
        name : "my name",
        logoUrl : "http://www...",
        campaigns : [
            {
                name : "my campaign name",
                timestamp : 1484172044462,
                nodes : [
                    {
                        property1 : "property1",
                        property2 : "property2"
                    }
                ]
             }
         ]
    }
]

That actually reflects nicely your graph model.

Moreover, since you are not doing RETURN COLLECT(...) this allows you to iterate over your Record result instead of getting the first (and only one) record and getting all the rows into it. This might be a convenience way when you are in situation like embedded server in which you can actually stream your result data instead of retrieve it in one shot.

This approach works pretty well even if you don't have any collections (eg one campaign has only one node) and also if the path gets deeper. However you may encounter challenges when your model is a tree (or worse, a graph).

You can find more details in this nice gist: https://gist.github.com/rherschke/9269173

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM