问题
I'm trying to transfert all ingoing and outgoing relationships (including their properties) from a node to another, before deleting the first one. they both have the same label.
The discussion started here : Neo4j Cypher : transfer all relationships before replacing a node by another
node_query = Neo4j::Session.query.match(old_node: {uuid: node1.uuid}).match(new_node: {uuid: node2.uuid})
types = node_query.match('node-[rel]-()').pluck('DISTINCT type(rel)')
types.each do |type|
node_query.match('old_node-[rel]->(other)').with(:old_node, :rel, :other).create("new_node-[new_rel]->other").set('new_rel = rel').exec
node_query.match('old_node<-[rel]-(other)').with(:old_node, :rel, :other).create("new_node<-[new_rel]-other").set('new_rel = rel').exec
end
When i tried to implement that i get this error
new_rel not defined (line 1, column 160)
"MATCH
(old_node {uuid: "YYYY"}),
(new_node {uuid: "XXXX"}),
oldnode-[rel]->(other)
WITH old_node, rel, other SET new_rel = rel
CREATE new_node-[new_rel]->other" ^
I tried another way which works only for the Neo4j::ActiveRel rels, beacause for the others there's no to_node property. It seems that it doesn't copy the relationship properties anyway :
relations = old_node.rels(dir: :outgoing)
relations.each do |rel|
if defined? rel.to_node
new_node.create_rel(rel.type, rel.to_node, rel.props)
end
end
relations = self.rels(dir: :incoming)
relations.each do |rel|
if defined? rel.from_node
rel.from_node.create_rel(rel.type, new_node, rel.props)
end
end
回答1:
Ah, now that I see the error I think I know what was wrong with the original answer. I'll look at your other solution too, but here is how I would fix the original (by adding a break to make the SET
come after the CREATE
):
# Assuming node already loaded
node_query = Neo4j::Session.query.match(node: {neo_id: node.neo_id}, new_node: {neo_id: new_node.neo_id})
types = node_query.match('node-[rel]-()').pluck('DISTINCT type(rel)')
types.each do |type|
node_query.match('node-[rel:#{type}]->(other)').
where('other <> new_node').
with(:node, :new_node, :rel, :other).
create("new_node-[new_rel:#{type}]->other").
break.set('new_rel = rel').exec
node_query.match('node<-[rel:#{type}]-(other)').
where('other <> new_node').
with(:node, :new_node, :rel, :other).
create("new_node<-[new_rel:#{type}]-other").
break.set('new_rel = rel').exec
end
回答2:
As to your other solution, I'm not too familiar with the rels
method (and I can't seem to find it), but I imagine it's returning either CypherRelationship
or ActiveRel
objects. I'm actually a bit surprised it only works if you define ActiveRel
models, because it should return CypherRelationship
objects if one isn't defined.
My guess as to your problem, though, is that you probably need to use start_node
and end_node
instead of from_node
and to_node
. We should probably standardize that...
EDIT : i'm editing this to add the Neo4j::Server::CypherRelationship that is returned when it's not an ActiveRel. there's no start_node nor from node :
{
"session": {
"connection": {
"parallel_manager": null,
"headers": {
"Content-Type": "application/json",
"User-Agent": "neo4j-gem/4.1.2 (https://github.com/neo4jrb/neo4j)",
"Authorization": "Basic realm=\"Neo4j\" OjdhYTUxNTcyYzBmMzBkYTMyNmY0NWQwMDc4ZTRlY2Rk"
},
"params": {},
"options": {
"params_encoder": null,
"proxy": null,
"bind": null,
"timeout": null,
"open_timeout": null,
"boundary": null,
"oauth": null
},
"ssl": {
"verify": null,
"ca_file": null,
"ca_path": null,
"verify_mode": null,
"cert_store": null,
"client_cert": null,
"client_key": null,
"certificate": null,
"private_key": null,
"verify_depth": null,
"version": null
},
"default_parallel_manager": null,
"builder": {
"handlers": [
{
"name": "Faraday::Request::BasicAuthentication",
"args": [
"neo4j",
"hroads"
],
"block": null
},
{
"name": "FaradayMiddleware::EncodeJson",
"args": [],
"block": null
},
{
"name": "FaradayMiddleware::ParseJson",
"args": [
{
"content_type": "application/json"
}
],
"block": null
},
{
"name": "Faraday::Adapter::NetHttpPersistent",
"args": [],
"block": null
}
],
"app": {
"header_value": "Basic bmVvNGo6aHJvYWRz",
"app": {
"app": {
"app": {
"app": {}
},
"options": {
"content_type": "application/json"
},
"content_types": [
"application/json"
]
}
}
}
},
"url_prefix": {
"scheme": "http",
"user": null,
"password": null,
"host": null,
"port": 80,
"path": "/",
"query": null,
"opaque": null,
"registry": null,
"fragment": null,
"parser": null
},
"proxy": null
},
"auth": {
"url": "http://localhost:7474",
"connection": {
"parallel_manager": null,
"headers": {
"Content-Type": "application/json",
"User-Agent": "neo4j-gem/4.1.2 (https://github.com/neo4jrb/neo4j)",
"Authorization": "Basic realm=\"Neo4j\" OjdhYTUxNTcyYzBmMzBkYTMyNmY0NWQwMDc4ZTRlY2Rk"
},
"params": {},
"options": {
"params_encoder": null,
"proxy": null,
"bind": null,
"timeout": null,
"open_timeout": null,
"boundary": null,
"oauth": null
},
"ssl": {
"verify": null,
"ca_file": null,
"ca_path": null,
"verify_mode": null,
"cert_store": null,
"client_cert": null,
"client_key": null,
"certificate": null,
"private_key": null,
"verify_depth": null,
"version": null
},
"default_parallel_manager": null,
"builder": {
"handlers": [
{
"name": "Faraday::Request::BasicAuthentication",
"args": [
"neo4j",
"hroads"
],
"block": null
},
{
"name": "FaradayMiddleware::EncodeJson",
"args": [],
"block": null
},
{
"name": "FaradayMiddleware::ParseJson",
"args": [
{
"content_type": "application/json"
}
],
"block": null
},
{
"name": "Faraday::Adapter::NetHttpPersistent",
"args": [],
"block": null
}
],
"app": {
"header_value": "Basic bmVvNGo6aHJvYWRz",
"app": {
"app": {
"app": {
"app": {}
},
"options": {
"content_type": "application/json"
},
"content_types": [
"application/json"
]
}
}
}
},
"url_prefix": {
"scheme": "http",
"user": null,
"password": null,
"host": null,
"port": 80,
"path": "/",
"query": null,
"opaque": null,
"registry": null,
"fragment": null,
"parser": null
},
"proxy": null
},
"params": {
"basic_auth": {
"username": "neo4j",
"password": "hroads"
}
},
"token": "7aa51572c0f30da326f45d0078e4ecdd"
},
"resource_url": "http://localhost:7474/db/data/",
"resource_data": {
"extensions": {},
"node": "http://localhost:7474/db/data/node",
"node_index": "http://localhost:7474/db/data/index/node",
"relationship_index": "http://localhost:7474/db/data/index/relationship",
"extensions_info": "http://localhost:7474/db/data/ext",
"relationship_types": "http://localhost:7474/db/data/relationship/types",
"batch": "http://localhost:7474/db/data/batch",
"cypher": "http://localhost:7474/db/data/cypher",
"indexes": "http://localhost:7474/db/data/schema/index",
"constraints": "http://localhost:7474/db/data/schema/constraint",
"transaction": "http://localhost:7474/db/data/transaction",
"node_labels": "http://localhost:7474/db/data/labels",
"neo4j_version": "2.2.0-M02"
}
},
"response_hash": {
"extensions": {},
"metadata": {
"id": 2000,
"type": "LEAD_TO"
},
"data": {
"created_at": 1422832907
},
"property": "http://localhost:7474/db/data/relationship/2000/properties/{key}",
"start": "http://localhost:7474/db/data/node/1266",
"self": "http://localhost:7474/db/data/relationship/2000",
"end": "http://localhost:7474/db/data/node/1264",
"type": "LEAD_TO",
"properties": "http://localhost:7474/db/data/relationship/2000/properties",
"id": 2000
},
"rel_type": "LEAD_TO",
"props": {
"created_at": 1422832907
},
"start_node_neo_id": 1266,
"end_node_neo_id": 1264,
"id": 2000
}
来源:https://stackoverflow.com/questions/28274009/neo4j-rb-transfer-all-relationships-before-replacing-a-node-by-another