2015-04-06 68 views
2

我試圖在LOAD CSV操作中設置多個關係屬性,其中一個屬性將始終設置,另一個只會在兩個節點屬於具體標籤。我似乎無法讓它允許我將多個SET語句鏈接在一起,並使用它們之間的條件。創建/設置多個關係屬性,有條件

我試圖做的線沿線的東西:

LOAD CSV WITH HEADERS FROM "file:/smalltext.csv" AS line 
MATCH (a:Person { username: line.sender }) 
MATCH (b:Person { username: line.recipient }) 
CREATE UNIQUE (a)-[r:MSGD ]->(b) 
SET r.Msg = coalesce(r.Msg, []) + [line.Msg] 
WITH a,b,r, WHERE a:Geotagged AND b:Geotagged, 
SET r.Distance = (2 * 6371 * asin(sqrt(haversin(radians(a.statusLat - b.statusLat)) + cos(radians(a.statusLat)) * cos(radians(b.statusLat)) * haversin(radians(a.statusLat - b.statusLon))))); 

僅供參考,距離公式直接來自Neo4j的,所以我相信這是正確的,不僅在數學,但語法上也是如此。

http://neo4j.com/docs/stable/query-functions-mathematical.html#functions-haversin

距離屬性應該設置當且僅當兩個節點都標記爲「帶有地理標記」。原因是,所有東西的減法函數都不知道如何從數字中減去空值(反之亦然),並且如果用戶不是「地理標籤」,經緯度值將爲空。

我已經嘗試在CREATE語句中創建Msg屬性,但它不會允許我從關係屬性內引用關係屬性。

當導入數據(也在LOAD CSV中)時設置「地理標籤」標籤,並且僅在每個用戶都具有地理位置信息時才設置標籤。

我也想知道如果我應該讓距離屬性成爲一個單獨的關係嗎?我寧願將它與信息放在一起,但也對這個問題持開放態度。

謝謝!

編輯1 我已經能夠設置經/緯度爲0,如果用戶沒有在初始節點創建階段進行地理標記,但我寧願不如果我不絕對有操縱數據至。

EDIT 2 之後將其具有的所有非地理標記的節點LAT和LON爲0,並重新運行關係進口,Cypher支架依然告訴我它無法與0做減法(見下文):

QueryExecutionKernelException:不知道如何 減(a.statusLat,b.statusLat)`0`用`33.223`

現在我只是困惑......我還以爲它不會有問題,但這是STILL不是一個好的解決方案,因爲當計算帶地理標記的用戶和未用地理標記的用戶之間的距離時,它會給出我無法使用的實際(和錯誤)結果。

編輯3 下面的答案確實工作,但上述我異常的原因是因爲我想減去上字符串(廢話),所以只需在減法的時候運行它們通過toFloat()固定它。我嘗試運行toFloat()並將結果存儲在數據庫中,但如果它返回NULL,則完全刪除該字段,這不是我所要做的行爲。

如果有人有辦法在相同的LOAD CSV操作中同時運行兩個SET,我將非常感謝您知道如何,因爲這對我的實際數據集來說遠非理想。

回答

2

我希望這不是一個愚蠢的建議,但...

......豈不是更簡單了將查詢分爲多個部分?沒有什麼可說的,您無法使用多個Cypher語句以多種方式導入和處理相同的CSV文件。從你的問題,我假設(a)-[r:MSGD ]->(b)關係的創建和r.msg屬性的設置工作正常。當試圖有條件地設置r.distance時,問題就出現了。於是再跑LOAD CSV操作,像這樣:

LOAD CSV WITH HEADERS FROM "file:/smalltext.csv" AS line 
MATCH (a:Person:Geotagged { username: line.sender })-[r:MSGD]->(b:Person:Geotagged { username: line.recipient }) 
SET r.Distance = (2 * 6371 * asin(sqrt(haversin(radians(a.statusLat - b.statusLat)) + cos(radians(a.statusLat)) * cos(radians(b.statusLat)) * haversin(radians(a.statusLat - b.statusLon))))); 

這應該與只與由MSGD關係聯繫,因此滿足您只設置r.distance財產都Person節點時的狀況都:Person:Geotagged標籤的節點已被標記爲Geotagged

完整的代碼會是這樣的:

LOAD CSV WITH HEADERS FROM "file:/smalltext.csv" AS line 
MATCH (a:Person { username: line.sender }) 
MATCH (b:Person { username: line.recipient }) 
CREATE UNIQUE (a)-[r:MSGD]->(b) 
SET r.Msg = coalesce(r.Msg, []) + [line.Msg] 

LOAD CSV WITH HEADERS FROM "file:/smalltext.csv" AS line 
MATCH (a:Person:Geotagged { username: line.sender })-[r:MSGD]->(b:Person:Geotagged { username: line.recipient }) 
SET r.Distance = (2 * 6371 * asin(sqrt(haversin(radians(a.statusLat - b.statusLat)) + cos(radians(a.statusLat)) * cos(radians(b.statusLat)) * haversin(radians(a.statusLat - b.statusLon))))); 

希望這是有幫助的。

+0

不,根本不是一個愚蠢的建議......我甚至沒有考慮過第二次在文件中閱讀。實際數據(300萬個節點和幾百萬個關係)會讓事情變得更加困難,但是......我仍然認爲有一種方法可以在一個聲明中完成,但這確實奏效。更多細節在我的OP。 – Brooks