Creating/Setting 多个关系属性,有条件
Creating/Setting multiple relationship properties, with conditional
我正在尝试在 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
如果且仅当两个节点都标记为 "Geotagged" 时,才应设置距离 属性。原因是,减法函数(在所有事物中)不知道如何从数字中减去 null(反之亦然),如果用户不是 "Geotagged",则 lat/lon 值将是空。
我尝试将 Msg 属性 的创建放在 CREATE 语句中,但它不允许我从关系 属性 中引用关系 属性 .
"Geotagged" 标签在导入数据时设置(也在 LOAD CSV 中),并且仅当每个用户都有地理位置信息时才会设置。
我也想过要不要把距离属性单独算一个关系?我宁愿将其与消息放在一起,但也愿意接受关于该问题的想法。
谢谢!
编辑 1
如果在初始节点创建阶段未对用户进行地理标记,我已经能够将 lat/lon 设置为 0,但是如果不是绝对必要,我宁愿不操作数据。
编辑 2
在将所有非地理标记节点的 LAT 和 LON 设置为 0 并重新运行 导入关系后,Cypher 仍然告诉我它不能用 0 进行减法(见下文):
QueryExecutionKernelException: Don't know how to
Subtract(a.statusLat,b.statusLat) `0` with `33.223`
现在我只是感到困惑...我原以为这不会有问题,但这 仍然 不是一个好的解决方案,因为在计算时地理标记和非地理标记用户之间的距离,它将给出我无法处理的实际(和错误)结果。
编辑 3
下面的答案确实有效,但是我上面的异常的原因是因为我试图在字符串上减去(duh),所以简单地 运行 在减法时通过 toFloat() 将它们固定它。我尝试 运行ning toFloat() 并将结果存储在数据库中,但是如果它返回 NULL,则完全删除该字段,这不是我想要的行为。
如果有人有办法在同一个 LOAD CSV 操作中 运行 两个 SET,我将非常感谢知道如何操作,因为这对我的实际数据集来说远非理想。
我希望这不是一个愚蠢的建议但是...
...将查询分成多个部分不是更简单吗?毫无疑问,您不能使用多个 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)))));
希望这对您有所帮助。
我正在尝试在 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
如果且仅当两个节点都标记为 "Geotagged" 时,才应设置距离 属性。原因是,减法函数(在所有事物中)不知道如何从数字中减去 null(反之亦然),如果用户不是 "Geotagged",则 lat/lon 值将是空。
我尝试将 Msg 属性 的创建放在 CREATE 语句中,但它不允许我从关系 属性 中引用关系 属性 .
"Geotagged" 标签在导入数据时设置(也在 LOAD CSV 中),并且仅当每个用户都有地理位置信息时才会设置。
我也想过要不要把距离属性单独算一个关系?我宁愿将其与消息放在一起,但也愿意接受关于该问题的想法。
谢谢!
编辑 1 如果在初始节点创建阶段未对用户进行地理标记,我已经能够将 lat/lon 设置为 0,但是如果不是绝对必要,我宁愿不操作数据。
编辑 2 在将所有非地理标记节点的 LAT 和 LON 设置为 0 并重新运行 导入关系后,Cypher 仍然告诉我它不能用 0 进行减法(见下文):
QueryExecutionKernelException: Don't know how to Subtract(a.statusLat,b.statusLat) `0` with `33.223`
现在我只是感到困惑...我原以为这不会有问题,但这 仍然 不是一个好的解决方案,因为在计算时地理标记和非地理标记用户之间的距离,它将给出我无法处理的实际(和错误)结果。
编辑 3 下面的答案确实有效,但是我上面的异常的原因是因为我试图在字符串上减去(duh),所以简单地 运行 在减法时通过 toFloat() 将它们固定它。我尝试 运行ning toFloat() 并将结果存储在数据库中,但是如果它返回 NULL,则完全删除该字段,这不是我想要的行为。
如果有人有办法在同一个 LOAD CSV 操作中 运行 两个 SET,我将非常感谢知道如何操作,因为这对我的实际数据集来说远非理想。
我希望这不是一个愚蠢的建议但是...
...将查询分成多个部分不是更简单吗?毫无疑问,您不能使用多个 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)))));
希望这对您有所帮助。