简体   繁体   中英

Neo4J - Copy all relationships from one to another node (C# Wrapper)

i'm currently struggling with an issue an i've not found any workaround at the moment. (I'm using NEO4J C# library)

I need to merge two nodes together into a third and copy all the relationships (Type & Properties) from those two nodes to my newly created third node:

(a:Label)-[r]-()
(b:Label)-[r2]-()
(c:Label)

I've been able to properly retrieve my two first nodes & merge it into a third node that's created in the DB, but i'm struggling to copy all relationships from the two firsts nodes to the third one.

I've tried several things without success, such as:

        using (GraphClient graphClient = GetGraphClient())
        {
            var inputString = string.Format("({0}:{1})-[r]->(n), ({2}:{3})", "a", typeof(Label).Name, "b", typeof(Label).Name);
            var query = graphClient.Cypher
                    .SendQueryOnMaster()
                    .Match(inputString)
                    .Where((Label a) => a.Id == from.Id)
                    .AndWhere((Label b) => b.Id == to.Id)
                    .Create("(b)-[r2:type(r)]->(n)");
            query.ExecuteWithoutResults();
        }

Copy all relationships from one node to another might be a use-case people might have encountered :)

Is There any way to make it work ?

Thanks

Update, i've found a way to copy all relationships from one node to another using C# wrapper.

    internal static void DuplicateRelationships<T>(T from, T to) where T : IDataObject
    {
        string aVariable = "a";
        string bVariable = "b";
        string nVariable = "n";
        string relationVariable = "r";
        string newRelation = "r2";
        string relationsVariable = "rels";
        string relationPostCollectVariable = "rel";

        Guid fromId = from.Id;
        Guid toId = to.Id;

        foreach (string relation in CypherVerbs.GetAllVerbs())
        {
            using (GraphClient graphClient = GetGraphClient())
            {
                /*-[r]->*/
                graphClient.Cypher
                    .SendQueryOnMaster()
                    .Match(string.Format("({0}:{1})-[{2}:{3}]->({4}), ({5}:{6})", aVariable, from.GetType().Name, relationVariable, relation, nVariable, bVariable, to.GetType().Name))
                    .Where((T a) => a.Id == fromId)
                    .AndWhere((T b) => b.Id == toId)
                    .With(string.Format("COLLECT({0}) AS {1}, {2}, {3}, {4}", relationVariable, relationsVariable, aVariable, bVariable, nVariable))
                    .ForEach(string.Format("({0} in {1} | ", relationPostCollectVariable, relationsVariable))
                    .Create(string.Format("({0})-[{1}:{2}]->({3})", bVariable, newRelation, relation, nVariable))
                    .Set(string.Format("{0} += {1})", newRelation, relationPostCollectVariable))
                    .ExecuteWithoutResults();

                /*<-[r]-*/
                graphClient.Cypher
                    .SendQueryOnMaster()
                    .Match(string.Format("({0}:{1})<-[{2}:{3}]-({4}), ({5}:{6})", aVariable, from.GetType().Name, relationVariable, relation, nVariable, bVariable, to.GetType().Name))
                    .Where((T a) => a.Id == fromId)
                    .AndWhere((T b) => b.Id == toId)
                    .With(string.Format("COLLECT({0}) AS {1}, {2}, {3}, {4}", relationVariable, relationsVariable, aVariable, bVariable, nVariable))
                    .ForEach(string.Format("({0} IN {1} | ", relationPostCollectVariable, relationsVariable))
                    .Create(string.Format("({0})<-[{1}:{2}]-({3})", bVariable, newRelation, relation, nVariable))
                    .Set(string.Format("{0} += {1})", newRelation, relationPostCollectVariable))
                    .ExecuteWithoutResults();
            }
        }
    }

Here is the cypher code:

MATCH (a:Test {props1:"1"}), (b:Test {props3:"3"})
WITH a,b
MATCH (a)-[r:LINKED_TO]->(c)
WITH COLLECT(r) AS rels, a, b, c
FOREACH (rel in rels |
       CREATE (b)-[r:LINKED_TO]->(c)
       SET r+=rel
)

EDIT: Since Neo4j 3.0 you can use stored procedure to execute this more efficiently, Michael Hunger developed several template stored procedure including the copy all relationships from one node to another procedure.

Here is the link to the stored procedure repository: https://github.com/neo4j-contrib/neo4j-apoc-procedures

Here is the link to the documentation for graph refactoring: https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_graph_refactoring

Unfortunately this isn't possible in Neo4j , I imagine you've found the other posts on StackOverflow for this:

It'd be possible if you know the Label of the relationship at compile time, but it won't work for multiple / dynamic label types. I'm sorry that there's not a better answer to give you on this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM