2015-11-25 105 views
2

我在一個顯然很簡單的查詢中失敗。Cypher:限制選定節點的返回鏈接的數量

ALGO:

  1. 排序一些值節點(降序):

    MATCH (n) WHERE has(n.II_VAL) WITH n, n.II_VAL as ShInflInd order by ShInflInd desc 
    
  2. 對於每個節點,返回其直接鄰居(由第二值訂購):

    MATCH (n)-[r]->(m) with n, m, m.VALUE as SubsOpRev order by SubsOpRev desc 
    

挑戰我s返回前100 n個節點,每個節點只有10個關係r(如果可能的話在一行中)。

編輯:

對不起,如此不特定的人理解我的意思。

詳細,下面的查詢給我頂節點,排序:

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"      | 

現在我可以子查詢添加到這裏面添加鏈接:

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  | 

現在我在返回10個「PUBLIC」鏈接(可能按r.WEIGHT_MERGED或SubsOpRev排序)後,查詢返回第二個節點(「BARCLAYS PLC」)及其10個鏈接等。

我試過:

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]; 

結果造成:

+------------------------------------------------------------------------------------------------------------------------------------------+ 
| collect([n.NAME, r.WEIGHT_MERGED, m.NAME, SubsOpRev])[0..3]                    | 
+------------------------------------------------------------------------------------------------------------------------------------------+ 
| [["PUBLIC",0.66,"VBS MUTUAL BANK",2630],["PUBLIC",0.2923,"STRATCORP LIMITED",10842], ... 

這意味着,我還是堅持了 「公開」。

修改查詢有點使事情變得更糟,因爲它返回完全不同的數據:

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]]     | 

理想的情況下,查詢應該產生類似

| [["PUBLIC",0.66,"VBS MUTUAL BANK",2630],["PUBLIC",0.2923,"STRATCORP LIMITED",10842], ... | 
| [["BARCLAYS PLC",x,"XYZ",y], ... | 

回答

1

你只需要限制,然後用您的查詢繼續。爲了提供一個可重現的例子,讓我們切換到Neo4j附帶的電影數據集。假設您想要抓取數據庫中最舊的3部電影,然後抓取每部電影中最老的2部演員。

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; 

這產生了:

| 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'] 

所以你想是這樣的:

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]; 
+0

這正是我需要的,謝謝。再次,我得到最後的列表再次按n.II_VAL排序:「... WITH n,n.II_VAL AS ii,r,m ORDER BY m.VALUE DESC RETURN n.NAME,ii,COLLECT([r.WEIGHT_MERGED, m.NAME,m.VALUE])[0..2] ORDER BY ii DESC;「 – jnode

0

你能描述的問題是什麼?

最大的問題似乎是你沒有用RETURN完成你的查詢。 WITH用於數據的中間傳遞。此外,您實際上不需要拉出價值來對其進行排序。你可以這樣做:

MATCH (n) 
WHERE has(n.II_VAL) 
RETURN n ORDER BY n.II_VAL DESC LIMIT 100 

對於你的第二個查詢:

MATCH (n)-[r]->(m) 
RETURN n, m ORDER BY m.VALUE DESC LIMIT 100 

編輯:對不起,忘了LIMIT

+0

查詢片段只意味着作爲例證。請參閱我的原始帖子的編輯。 – jnode

0

要根據你的第一個查詢獲得前100個節點,你必須在訂單後添加一條RETURN條款和一條LIMIT一條:

MATCH (n) 
WHERE has(n.II_VAL) 
RETURN n, n.II_VAL as ShInflInd 
order by ShInflInd desc 
LIMIT 100 

對於第二個,你必須做兩個查詢,並在客戶端實現Foreach邏輯。因爲您不能將第一個節點限制爲100,然後爲您在相同查詢中獲得的每個節點獲取10個相關節點。

+0

我沒有管理循環。請參閱我的原始帖子的編輯。 – jnode

1

您可以限制節點的數量爲100:

MATCH (n) 
WHERE has(n.II_VAL) 
WITH n, n.II_VAL AS ShInflInd 
ORDER BY ShInflInd DESC 
LIMIT 100 

你可以收集你的所有託收SubsOpRev然後RETURN片。沿着這條線的東西(我假設SubsOpRev是你想要的):

MATCH (n)-[r]->(m) 
WITH n, m.VALUE AS SubsOpRev 
ORDER BY SubsOpRev DESC 
RETURN n, collect(DISTINCT SubsOpRev)[1..10] 

這會給你每行一個節點n和所有收集到的SubsOpRev的列表的片段。

+0

我需要結合這兩個查詢。請參閱我的原始帖子的編輯。 – jnode

+0

你可以合併它們。關於你的編輯:你必須首先「訂購」,然後「收集()」只有你想返回的關係或值。如果您想再次使用相同的節點順序,則可能需要在「RETURN」中重新排序。 –

+0

是的,但我需要爲從第一次排序搜索中獲得的每個節點添加一個子查詢(檢索10個鏈接)。我不知道如何以非平凡的方式組合查詢... – jnode

0

我想你所說的是你想在一個查詢中返回兩組結果。要做到這一點,我認爲最好的做法是collectWITH這將給你一行,然後RETURN與其他數據的collect一起。喜歡的東西:

MATCH (n) WHERE HAS(n.II_VAL) 
WITH collect([n, n.`II_VAL`])[0..100] AS set1 ORDER BY n.`II_VAL` DESC 
MATCH (n)-[r]->(m) WHERE HAS(m.VALUE) 
RETURN set1, collect([n.NAME, r.WEIGHT_MERGED, m.NAME])[1..10] ORDER BY r.WEIGHT_MERGED 

我在ORDER BY r.WEIGHT_MERGED扔的爲例的如何,你可以通過值再次排序。

如果你想讓你的數據更多的結構化的,你還可以收集對象映射,而不是像這樣的數組:

MATCH (n) WHERE HAS(n.II_VAL) 
WITH collect({n: n, II_VAL: n.`II_VAL`})[0..100] AS set1 ORDER BY n.`II_VAL` DESC 
MATCH (n)-[r]->(m) WHERE HAS(m.VALUE) 
RETURN set1, collect({n_name: n.NAME, weight_merged: r.WEIGHT_MERGED, m_name: m.NAME})[1..10] ORDER BY r.WEIGHT_MERGED 
+0

OK,close :)但是,查詢並不知道第二行中的「n」(「n not defined」)(ORDER BY n.'II_VAL')。如果我在「WITH」之後添加它(WITH n,collect({n ...),我將n.'II_VAL'的原始排序鬆開。但它返回的結構看起來像我正在尋找的... – jnode

+0

您將'bound'放在'WITH'子句之外就失去了綁定的'n';此時,您只是在第3行的所有節點上匹配。 –

相關問題