我尝试在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
距离属性应设置为IF,并且仅在两个节点都标记为" Geotagged"时。原因是,(所有事物的)减法函数不知道如何从数字中减去空值(反之亦然),如果用户不是"地理标记&#34 ;,纬度/经度值将为null。
我已尝试在CREATE语句中创建Msg属性,但它不允许我从关系属性中引用关系属性。
" Geotagged"导入数据时(也在LOAD CSV中)设置标签,仅当每个用户都有地理位置信息时才设置标签。
我还想知道我是否应该将距离属性作为一个单独的关系?我宁愿将它与消息保持在一起,但我也对这个问题有所了解。
谢谢!
编辑1 如果用户在初始节点创建阶段没有进行地理标记,我已经能够将lat / lon设置为0,但是如果我不是必须的话,我宁愿不操纵数据。
编辑2 在设置了所有非地理标记节点之后' LAT和LON为0并重新运行关系导入,Cypher仍然告诉我它不能用0进行减法(见下文):
QueryExecutionKernelException:不知道如何操作 用`33.223`减去(a.statusLat,b.statusLat)`0`
现在我只是感到困惑......我认为它不会有问题,但这是 STILL 不是一个好的解决方案,因为在计算时地理标记和非地理标记用户之间的距离,它将给出我无法使用的实际(和错误)结果。
编辑3 下面的答案确实有效,但上面我的例外的原因是因为我试图减去字符串(duh),所以在减法时简单地通过toFloat()运行它们来修复它。我尝试运行toFloat()并将结果存储在数据库中,但是如果它返回NULL则完全删除了该字段,这不是我想要的行为。
如果有人有办法在同一个LOAD CSV操作中运行两个SET,我会非常感激知道如何,因为这与我的实际数据集相差甚远。
答案 0 :(得分:3)
我希望这不是一个愚蠢的建议,但是......
...将查询分成多个部分会不会更简单?没有什么可说的,你不能使用多个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)))));
这应仅匹配那些:Person
和:Geotagged
标签的节点,这些节点通过MSGD
关系链接,因此只满足您设置r.distance
属性的条件时两个Person
个节点都标有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)))));
希望这有用。