简体   繁体   中英

Cypher Query to return x Number of a particular type of node

Lets say we have a Neo4j graph such as (Brand)-[:from]->(Post)<-[:likes]-(Person).

How can I return a cypher query which will have a minimum number of brand posts, say 3. I want this to be scalable and not dependent on a specific property attribute value.

Hence the results would return at least 3 instances of the Brand nodes, as well as maybe 5 from Post and 15 from Person.

I have tried a few different things:

1.) Declare several variable names for each brand (not scalable)

    Match (b:Brand)-[]->(p:Post)<-[]-(per:Person) 
    Match (b1:Brand)-[]->(p1:Post)<-[]-(per2:Person)
    Match (b2:Brand)-[]->(p2:Post)<-[]-(per3:Person)
    return b,b1,b2,p,p1,p2,per,per2,per3
    limit 30

This didn't work because it essentially return the same as

    Match (b:Brand)-[]->(p:Post)<-[]-(per:Person) 
    return b,p,per
    limit 30

2.) Use a foreach some

    Match (b:Brand) WITH collect (distinct b) as bb 
    FOREACH (b in bb[0..3] | MATCH (b)-[]->(p:Post)<-[]-(per:Person)) 
    RETURN b, p, per LIMIT 40 

This didn't work because you can't use Match inside a Foreach call.

The only way I know how to do this is to declare a where clause with their unique property brand name values which is not scalable. It looks like this:

    Match (b:Brand)-[]->(p:Post)<-[]-(per:Person) 
    where b.brand = "b1" OR b.brand   ="b2" or b.brand = "b3"
    Return b,p,per  
    Limit 30 

However the above still doesn't even return what I want.

Please help. Here is a quick graph to test on:

    Create (b1:Brand {brand:'b1'})
    Create (b2:Brand {brand:'b2'})
    Create (b3:Brand {brand:'b3'})
    Create (p1:Post {id: "001",message: "foo"})
    Create (p2:Post {id: "002",message: "bar"})
    Create (p3:Post {id: "003",message: "baz"})
    Create (p4:Post {id: "004",message: "raz"})
    Create (per1:Person {id: "001",name: "foo"})
    Create (per2:Person {id: "002",name: "foo"})
    Create (per3:Person {id: "003",name: "foo"})
    Create (per4:Person {id: "004",name: "foo"})
    Create (per5:Person {id: "005",name: "foo"})
    Create (per6:Person {id: "006",name: "foo"})
    Create (per7:Person {id: "007",name: "foo"})
    Merge (b1)-[:FROM]->(p1)       
    Merge (b1)-[:FROM]->(p2)
    Merge (b2)-[:FROM]->(p3)
    Merge (b3)-[:FROM]->(p4)
    Merge (per1)-[:LIKES]->(p1)
    Merge (per1)-[:LIKES]->(p2)
    Merge (per1)-[:LIKES]->(p3)
    Merge (per2)-[:LIKES]->(p1)
    Merge (per2)-[:LIKES]->(p4)
    Merge (per3)-[:LIKES]->(p3)
    Merge (per4)-[:LIKES]->(p1)
    Merge (per5)-[:LIKES]->(p2)
    Merge (per6)-[:LIKES]->(p1)
    Merge (per6)-[:LIKES]->(p2)
    Merge (per6)-[:LIKES]->(p3)
    Merge (per6)-[:LIKES]->(p4)
    Merge (per7)-[:LIKES]->(p4)

You can use the unwind instead of foreach :

Match (b:Brand) WITH collect (distinct b) as bb 
UNWIND bb[0..3] as b
    MATCH (b)-[]->(p:Post)<-[]-(per:Person)
RETURN b, p, per LIMIT 40 

Or combine with and limit :

MATCH (b:Brand) WITH distinct b LIMIT 3
MATCH (b)-[]->(p:Post)<-[]-(per:Person)
RETURN b, p, per LIMIT 40 

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