I am failing at an apparently simple query.
Algo:
Sort nodes by some value (desc):
MATCH (n) WHERE has(n.II_VAL) WITH n, n.II_VAL as ShInflInd order by ShInflInd desc
For each node, return its direct neighbors (ordered by a second value):
MATCH (n)-[r]->(m) with n, m, m.VALUE as SubsOpRev order by SubsOpRev desc
The challenge is to return the top 100 n nodes and for each of them only 10 relations r (if possible in a single row).
EDIT:
Sorry for being so unspecific that people understood me wrong.
In detail, the following query gives me the top nodes, sorted:
MATCH (n) WHERE HAS(n.II_VAL)
WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC
RETURN n.NAME LIMIT 100;
+--------------------------------------+
| n.NAME |
+--------------------------------------+
| "PUBLIC" |
| "BARCLAYS PLC" |
Now I can add the sub-query to this which adds the links:
MATCH (n) WHERE HAS(n.II_VAL)
WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC LIMIT 100
MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
WITH r, n, m, m.VALUE AS SubsOpRev
RETURN n.NAME, r.WEIGHT_MERGED, m.NAME, SubsOpRev LIMIT 10;
+----------------------------------------------------------------------------------------+
| n.NAME | r.WEIGHT_MERGED | m.NAME | SubsOpRev |
+----------------------------------------------------------------------------------------+
| "PUBLIC" | 0.66 | "VBS MUTUAL BANK" | 2630 |
| "PUBLIC" | 0.2923 | "STRATCORP LIMITED" | 10842 |
Now what I would like, is that after returning 10 links for "PUBLIC" (possibly sorted by r.WEIGHT_MERGED or SubsOpRev) the query returns the second node ("BARCLAYS PLC") and its 10 links, etc.
I have tried:
MATCH (n) WHERE HAS(n.II_VAL)
WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC
MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
WITH r, n, m, m.VALUE AS SubsOpRev
RETURN collect([n.NAME, r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..10];
Resulting in:
+------------------------------------------------------------------------------------------------------------------------------------------+
| collect([n.NAME, r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..3] |
+------------------------------------------------------------------------------------------------------------------------------------------+
| [["PUBLIC",0.66,"VBS MUTUAL BANK",2630],["PUBLIC",0.2923,"STRATCORP LIMITED",10842], ...
which means I am still stuck with "PUBLIC".
Modifying the query a little makes things worse, as it returns totally different data:
MATCH (n) WHERE HAS(n.II_VAL)
WITH n, n.`II_VAL` AS ShInflInd ORDER BY ShInflInd DESC
MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
WITH r, n, m, m.VALUE AS SubsOpRev
RETURN n.NAME, collect([r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..10] LIMIT 3;
+------------------------------------------------------------------------------+
| n.NAME | collect([r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..10] |
+------------------------------------------------------------------------------+
| "RS-INVEST AS" | [[0.5,"VERUCO EIENDOM AS",100]] |
| "DBM" | [[0.1435,"CHELYABINSKOBLGAZ",6752]] |
Ideally, the query should yield something like
| [["PUBLIC",0.66,"VBS MUTUAL BANK",2630],["PUBLIC",0.2923,"STRATCORP LIMITED",10842], ... |
| [["BARCLAYS PLC",x,"XYZ",y], ... |
You just need to limit and then continue with your query. To provide a reproducible example, let's switch to the movie dataset that ships with Neo4j. Let's say you want to grab the 3 oldest movies in the database and then the 2 oldest actors in each of those movies.
MATCH (m:Movie)
WITH m ORDER BY m.released LIMIT 3
MATCH (p:Person)-[:ACTED_IN]->(m)
WITH m, p ORDER BY p.born
WITH m, COLLECT(p.name)[0..2] AS oldest
RETURN m.title, oldest;
This yields:
| m.title | oldest
---+---------------------------------+--------------------------------------
1 | Something's Gotta Give | ['Jack Nicholson', 'Diane Keaton']
2 | Top Gun | ['Tom Skerritt', 'Kelly McGillis']
3 | One Flew Over the Cuckoo's Nest | ['Jack Nicholson', 'Danny DeVito']
So you'll want something like this:
MATCH (n) WHERE HAS(n.II_VAL)
WITH n ORDER BY n.II_VAL DESC LIMIT 100
MATCH (n)-[r]->(m) WHERE HAS(m.VALUE)
WITH n, r, m ORDER BY m.VALUE DESC
RETURN n.NAME, COLLECT([r.WEIGHT_MERGED, m.NAME, m.VALUE])[0..10];
You can limit the number of nodes to 100:
MATCH (n)
WHERE has(n.II_VAL)
WITH n, n.II_VAL AS ShInflInd
ORDER BY ShInflInd DESC
LIMIT 100
You can collect all SubsOpRev and then RETURN a slice of your collection. Something along this line (I assume the SubsOpRev is what you want):
MATCH (n)-[r]->(m)
WITH n, m.VALUE AS SubsOpRev
ORDER BY SubsOpRev DESC
RETURN n, collect(DISTINCT SubsOpRev)[1..10]
This will give you one node n per row and a slice of the list of all collected SubsOpRev.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With