Search code examples
neo4jcypher

Sort paths by numeric sum


I have the following graph

(a1:A {name:'a1', s:1})  ->                            -> (a3:A {name:'a3',s:11})
(a2:A {name:'a2', s:10}) -> (b1:B) -> (c1:C) -> (b2:B) -> (a4:A {name:'a4',s:123})

On the left, there are 2 type A nodes that connect to the same type B node on the left. On the right, there are 2 type A nodes that connect to another type B node on the right. Each type A node has an attribute called s which indicates a score.

If I do a simple query like this

match p=((a1:A)--(b1:B)--(:C)--(b2:B)--(a2:A))
where a1.name in ['a1', 'a2']
return p

I will get 4 paths without any ordering. However, i would like the path to be order based on the aggregate score of the type A nodes on both end of the path, i.e,

(:A {name:'a2', s:10}) -> (b1:B) -> (c1:C) -> (b2:B) -> (:A {name:'a4',s:123})
(:A {name:'a1', s:1}) -> (b1:B) -> (c1:C) -> (b2:B) -> (:A {name:'a4',s:123})
(:A {name:'a2', s:10}) -> (b1:B) -> (c1:C) -> (b2:B) -> (:A {name:'a3',s:11})
(:A {name:'a1', s:1}) -> (b1:B) -> (c1:C) -> (b2:B) -> (:A {name:'a3',s:11})

Can I achieve this by cypher?


Solution

  • One option is to add the score to each path:

    match p=((a1:A)--(b1:B)--(:C)--(b2:B)--(a2:A))
    where a1.name in ['a1', 'a2']
    WITH p, a1.s + a2.s AS score
    return p, score
    ORDER BY score DESC
    

    If I use it on this sample data:

    MERGE (a1:A{name:'a1', s:1, key: 0})
    MERGE (a2:A{name:'a2', s:10, key: 1})
    MERGE (b1:B{key: 2})
    MERGE (c1:C{key: 3})
    MERGE (b2:B{key: 4})
    MERGE (a3:A{name:'a3',s:11, key: 5})
    MERGE (a4:A{name:'a4',s:123, key: 6})
    
    MERGE (a1)-[:LINKS]-(b1)
    MERGE (a2)-[:LINKS]-(b1)
    MERGE (b1)-[:LINKS]-(c1)
    MERGE (c1)-[:LINKS]-(b2)
    MERGE (b2)-[:LINKS]-(a3)
    MERGE (b2)-[:LINKS]-(a4)
    

    The result is:

    ╒══════════════════════════════════════════════════════════════════════╤═══════╕
    │"p"                                                                   │"score"│
    ╞══════════════════════════════════════════════════════════════════════╪═══════╡
    │[{"name":"a2","s":10,"key":1},{},{"key":2},{"key":2},{},{"key":3},{"ke│133    │
    │y":3},{},{"key":4},{"key":4},{},{"name":"a4","s":123,"key":6}]        │       │
    ├──────────────────────────────────────────────────────────────────────┼───────┤
    │[{"name":"a1","s":1,"key":0},{},{"key":2},{"key":2},{},{"key":3},{"key│124    │
    │":3},{},{"key":4},{"key":4},{},{"name":"a4","s":123,"key":6}]         │       │
    ├──────────────────────────────────────────────────────────────────────┼───────┤
    │[{"name":"a2","s":10,"key":1},{},{"key":2},{"key":2},{},{"key":3},{"ke│21     │
    │y":3},{},{"key":4},{"key":4},{},{"name":"a3","s":11,"key":5}]         │       │
    ├──────────────────────────────────────────────────────────────────────┼───────┤
    │[{"name":"a1","s":1,"key":0},{},{"key":2},{"key":2},{},{"key":3},{"key│12     │
    │":3},{},{"key":4},{"key":4},{},{"name":"a3","s":11,"key":5}]          │       │
    └──────────────────────────────────────────────────────────────────────┴───────┘