2014-03-26 63 views
0

我有一個分析用例,我用一系列不同的屬性將一堆節點堆放到Neo4j中。它們來自不同的系統和不同的表格,但是在各種節點類型中都有共享屬性(信息通過ETL過程)。高效的Cypher更新查詢以捕獲「已發現」關係

我想要做的就是查詢所有具有屬性(例如customer_id)的節點的圖並找到所有具有相同值的屬性的其他節點並在它們之間創建邊,捕獲任何任意匹配。

我根據源表標記節點期間的節點,我已經創建鏈接屬性的自動索引,並且我已經將標籤添加到具有公共屬性的節點,以便我可以將標籤索引放在它們上,但我沒有偶然發現正確的語法來有效地建立所有連接。

我想保留在Cypher中,因爲客戶可能會要求不同的觀點,所以我們可能會根據其他類型的匹配(如此「發現」的關係)發明新的邊緣,而不是滿足模式進入,然後能夠使用發現的邊來執行遍歷,回答您在關聯之前不能問的問題。

我的測試套件有900萬個節點,我迄今爲止所做的許多嘗試都表現不佳。

這是一個天真的嘗試,實際上對付少量的節點,但不能很好地擴展。你會如何處理這個問題?我認爲有一些方法可以高效地使用集合來完成此操作,但我還沒有制定出這種語法。

這是一個天真的嘗試,它適用於一小部分節點,但不能很好地擴展。

using periodic commit 100 match (a:CUST_ID_NODES), (b:CUST_ID_NODES) where a.customer_id=b.customer_id create unique (a)-[r:CUSTOMER_ID {customer_id: a.customer_id}]-(b);

回答

2

這是否可以對財產進行.customer_id加入標籤:CUST_ID_NODES組節點?如果是這樣,您最好創建關於攝取的關係。這聽起來像你爲未來可能創建的視圖定義索引,但我不認爲這比從一開始就創建所有你認識的視圖更便宜或更容易。

如果你仍然想在密碼中做到這一點,這裏有一些想法。您當前的查詢執行爲:將所有客戶ID節點匹配爲a;對於每個a,將所有客戶ID節點匹配爲b;過濾共享.customer_id。如果您擁有100 000個客戶ID節點,那麼要對共享媒體資源進行過濾10 000 000 000條結果,而對進行過濾則不會使用索引。查詢的第一個改進可能是從.customer_id的每個不同值開始,並從索引中查找具有該值的節點。假設你有一個像

CREATE INDEX ON :CUST_ID_NODES(customer_id) 

指數做到這一點,讓每CUSTOMER_ID節點

MATCH (a:CUST_ID_NODES) 
WITH DISTINCT a.customer_id as id 
MATCH (a:CUST_ID_NODES {customer_id:id}) 
// You can continue with flat (id, a) rows, or collect a per id 
// and do stuff in a FOREACH loop, something like: 
WITH id, collect(a) as aa 
MERGE (common {customer_id:id}) 
FOREACH (a IN aa | MERGE a-[:COMMON]->common) 

現在查詢得到的節點時,得到的值來查找節點上的不同的列表,而這個時間使用標籤索引。

然後有不同的方式來連接這些節點。您將每個節點與每個共享其ID的節點相關聯。最好的表示取決於你以後如何查詢圖表。如果想法是共享customer_id的節點表示相同的事物並且因此可以合併,則最簡單的方式可能是將共享性表示爲新節點並且將共享節點與它關聯,或者將共享屬性和關係從將節點共享到新節點中。但是我仍然不相信在密碼學中,而不是在ETL和攝取過程中這樣做是有好處的 - 它似乎只是在Talend或Pentaho中進行變換的一個步驟。

+0

謝謝,jjaderberg。我同意這樣做是最好的,但它假設我們理解可以被查詢的所有方式,我們不這麼做 - 或者至少我們不想限制它,所以我們最終會想要隨時添加新的關係。您的示例查詢看起來不錯,我會與它合作並報告回來。 – Vramin

+0

我想你讓我走在正確的軌道上。如果我沒有弄錯,上面描述的查詢的確會創建一個新節點或超級節點,當它合併到_common_中時。我大部分都在工作,但我在最後的合併中錯過了一些東西。當我給_common_添加一個新標籤時,我可以查詢它,但是:COMMON關係不會被創建。我會在新回覆中粘貼我的內容 - 我已經填充了這個文本框。 – Vramin

+0

@Vramin如果給出的答案之一適合你的問題,你可以接受它,如果沒有,你可以添加評論或澄清你的問題。如果你有跟進不明確的問題,最好單獨發佈;如果您發佈後續問題作爲答案(論壇風格),則沒有人能真正回答您。 – jjaderberg

0

如果節點A和B具有相同的CUSTOMER_ID,你應該建立在兩個方向上它們之間的關係?這似乎並不是一件非常有效率的事。我認爲你可以非常簡單地避免創建這些關係。

我的建議是:

  1. 你給所有節點與CUSTOMER_ID屬性相同的標籤,說「客戶」。一個節點可以有多個標籤,所以你可以合法地將這個額外的標籤添加到已有標籤的節點。
  2. 創建一個基於該標籤和屬性的索引:

    CREATE INDEX ON:客戶(CUSTOMER_ID);

然後,每當你需要找到所有具有相同CUSTOMER_ID的節點,可以有效地做到這一點:

MATCH (c:Customer {customer_id:{id}}) RETURN c; 
+0

謝謝,cybersam。我確實在CUST_ID_NODES標籤的customer_id字段上創建了索引,所以我應該能夠高效地獲取客戶標識符。但是,我們希望能夠根據各種遍歷查詢圖表,因此創建關係是關鍵。 CUST_ID_NODES標籤將來自展示此屬性的所有源的所有節點組合在一起,但現在這些關係可以讓我遍歷類型,而不必知道客戶ID(從產品開始,找到購買它的客戶,或找到客戶的朋友誰買了等)。 – Vramin