2015-04-06 44 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