Creating relationship with name as a variable. (RD

2019-04-15 09:30发布

I'm trying to migrate our current data set to Neo4J and was fairly successful so far until I reach this problem. I'm trying to create a set of relationships between 2 node where the name of the relationship is a variable. In my MySQL database, I have Role object which map to a pair of (Resource, Action) so I'm trying to convert it to Neo4J with data model such as (Role)-[Action]->(Resource). This is what I have but this doesn't seem like valid syntax:

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///roletoresourceaction.csv" AS row
MATCH (role:Role {roleId: row.ROLE_ID})
MATCH (resource:Resource {resourceId: row.RESOURCE_ID})
MATCH (action:Action {actionId: row.ACTION_ID})
MERGE (role)-[r:action.name]->(roleAsResource)

Would appreciate any help on this. Thanks.

标签: neo4j cypher
2条回答
闹够了就滚
2楼-- · 2019-04-15 09:58

This solution worked for me

LOAD CSV WITH HEADERS FROM "file:///roletoresourceaction.csv" AS row
MATCH
  (role:Role {roleId: row.ROLE_ID}),
  (resource:Resource {resourceId: row.RESOURCE_ID}),
  (action:Action {actionId: row.ACTION_ID})
OPTIONAL MATCH (role)-[rel]->(resource)
WITH role, resource, action, COLLECT(TYPE(rel)) AS relTypes
WHERE NOT action.name IN relTypes
CALL apoc.create.relationship(role, action.name, NULL, resource)      YIELD rel
RETURN role, resource, rel;
查看更多
做自己的国王
3楼-- · 2019-04-15 10:02

Neo4j 3.x added support for apoc procedures (which must be installed on the server before they can be used).

With the apoc procedure apoc.create.relationship, you should be able to do the equivalent of a MERGE of dynamic relationship types. The Cypher language, by itself, only supports the creation/merging of static relationship types.

Hopefully, this works for you:

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///roletoresourceaction.csv" AS row
MATCH
  (role:Role {roleId: row.ROLE_ID}),
  (resource:Resource {resourceId: row.RESOURCE_ID}),
  (action:Action {actionId: row.ACTION_ID})
OPTIONAL MATCH (role)-[rel]->(resource)
WITH role, resource, action, COLLECT(TYPE(rel)) AS relTypes
WHERE NOT action.name IN relTypes
CALL apoc.create.relationship(role, action.name, NULL, resource) YIELD newRel
RETURN role, resource, newRel;

The OPTIONAL MATCH and WHERE clauses verify that the relationship does not already exist before allowing apoc.create.relationship to create it.

ASIDE: I was also hoping to use the apoc.path.expand procedure instead of the OPTIONAL MATCH clause (with some additional changes), but that procedure currently seems to abort the query when it fails to find a match -- even testing the returned path for NULL does not help.

查看更多
登录 后发表回答