将WITH / CASE子句链接在一起

时间:2015-04-03 15:03:39

标签: neo4j cypher

我正在尝试为节点设置标签,以便在通过LOAD CSV语句创建它们时对其进行适当的表征(请参阅我在此过程中的早期问题:SET label based on data within LOAD CSV)。我已经能够在创建阶段设置一个标签,但现在我想应用多个标签中的一个,每个标签都有自己的一套条件,每个标签互相排斥。

因此,如果我的CSV文件中包含以下内容:

"username","id","latitude","longitude","placeLatitude","placeLongitude"
"abc123","111111111","33.223","33.223"
"abc456","222222222","","","33.223","33.223"

我希望用户abc123标记为“geo”,用户abc456标记为“placegeo”。这似乎是Neo4j / Cypher应该能够轻松完成的事情,但似乎存在限制,因为我希望所有的决策都在一个声明中完成。

我一直在尝试以下代码:

LOAD CSV WITH HEADERS FROM "file:d:/Users.csv" AS line
CREATE (p:Person { username: line.username, id: line.id, statusLat: line.statusLat, statusLon: line.statusLon, placeLat: line.placeLat, placeLon: line.placeLon })
WITH p, CASE WHEN (line.statusLat <> "" AND line.statusLat <> "0.0") THEN [1] ELSE [] END AS geotagged
FOREACH (a IN geotagged | SET p:Geo)
WITH p, CASE WHEN (COUNT(LABELS(p)) = 1 AND line.placeLat <> "" AND line.placeLat <> "0.0") THEN [1] ELSE [] END as place
FOREACH (b IN place | SET p:placegeo);

我也尝试过:

LOAD CSV WITH HEADERS FROM "file:d:/Users.csv" AS line
CREATE (p:Person { username: line.username, id: line.id, statusLat: line.statusLat, statusLon: line.statusLon, placeLat: line.placeLat, placeLon: line.placeLon })
WITH p, CASE WHEN (line.statusLat <> "" AND line.statusLat <> "0.0") THEN [1] ELSE [] END AS geotagged
FOREACH (a IN geotagged | SET p:Geo)
WITH p, COUNT(LABELS(p)) AS lb WHERE lb = 1,
CASE WHEN (line.placeLat <> "" AND line.placeLat <> "0.0") THEN [1] ELSE [] END as place
FOREACH (b IN place | SET p:placegeo);

(在其他变体中)似乎我不能将WITH / CASE语句链接在一起。

基本上,我想评估第一组条件,如果符合条件,请添加标签STOP,然后转到CSV文件的下一行。否则转到下一组条件并重复。如果我可以在SET中发出“STOP”或“EXIT”命令,那就没问题了。

由于互相排斥(即如果它是一个标签,它不是另一个标签),我无法嵌套FOREACH。

有没有这样做?

1 个答案:

答案 0 :(得分:2)

你非常接近。这应该适合你:

LOAD CSV WITH HEADERS FROM "file:d:/Users.csv" AS line
CREATE (p:Person { username: line.username, id: line.id, statusLat: line.statusLat, statusLon: line.statusLon, placeLat: line.placeLat, placeLon: line.placeLon })
WITH p,
    CASE WHEN (line.statusLat <> "" AND line.statusLat <> "0.0") THEN [1] ELSE [] END AS geotagged,
    CASE WHEN ((line.statusLat = "" OR line.statusLat = "0.0") AND line.placeLat <> "" AND line.placeLat <> "0.0") THEN [1] ELSE [] END as place
FOREACH (a IN geotagged | SET p:Geo)
FOREACH (b IN place | SET p:placegeo);