Search code examples
c#neo4jcypherneo4jclient

How do I return Relationship and its properties through neo4jclient with cypher


Please find below the Cypher Query (which is normal)

MATCH (a:`Entity`) - [r] - (b:`Entity`)
RETURN a , r , b

First Question : How do I translate this to neo4jClient in my c# Code.

Second Question : The Relation has multiple properties. How do I access them as well using neo4Jclient ?

Entity has Properties EntityName and DataSpaceName The Relation has Properties RelationType and RelationFrequency.

The Code I have used for fetching the node details, is as below

var query1 = client
        .Cypher
        .Match("(a:`Entity`) - [r] - (b:`Entity`)") 
        .Where("a.DataSpace = b.DataSpace")
        .Return((a,b) => new {
            FromEntity = Return.As<string>("a.EntityName"),
            ToEntity=Return.As<string>("b.EntityName")
            }
        );

EDIT :

I had tried to figure it. The following worked.

var query1 = client
        .Cypher
        .Match("(a:`Entity`) - [r] - (b:`Entity`)") 
        .Where("a.DataSpace = b.DataSpace")
        .Return((a,b) => new {
            FromEntity = Return.As<string>("a.EntityName"),
            ToEntity=Return.As<string>("b.EntityName"),
            Relation=Return.As<string>("r.RelType"),

            }
        );

However, if the relation is a wild card, namely [*] or [r *1..3], how will I fetch the properties of the relation.


Solution

  • Relationship objects are the same as node objects, so you get them in the same way.

    How have you actually got your elements set up? What is an 'Entity', assuming you have a class like:

    public class Entity {
        public string DataSpace { get; set; }
        public string EntityName { get; set; }
    }
    

    and a Relationship object:

    public class RelationshipObj {
        public string RelType { get; set; }
    }
    

    You would return with something like this:

    var originalQuery = graphClient
        .Cypher
        .Match("(a:`Entity`)-[r]-(b:`Entity`)")
        .Where("a.DataSpace = b.DataSpace")
        .Return((a, b, r) => new
        {
            FromEntity = a.As<Entity>().EntityName,
            ToEntity = b.As<Entity>().EntityName,
            Relation = r.As<RelationshipObj>().RelType,
        });
    

    In the situation where you have [r*1..3] you end up with a more complex query as you're returning an enumeration instead. So you're return for 'Relation' becomes:

    Relation = r.As<IEnumerable<RelationshipObj>>()
    

    Which you can no longer pull the 'RelType' property from without parsing the results later:

    foreach (var result in results)
    {
        foreach (var relationship in result.Relation)
        {
            Console.WriteLine(relationship.RelType);
        }
    }
    

    Now, you actually ask how to cope with a wildcard relationship, obviously you can't get the properties as above - as you don't actually know what you're asking for. You can get the results as a string and use JSON.NET to parse it to the right object. However, you can also return RelationshipInstance<Dictionary<string,string>> which will give you the TypeKey for the relationship, which you can use to deserialize into your relationship object:

    var query = graphClient.Cypher
        .Match("(a:`Entity`)-[r*]-(b:`Entity`)")
        .Where("a.DataSpace = b.DataSpace")
        .Return((a, b, r) => new
        {
            FromEntity = a.As<Entity>().EntityName,
            ToEntity = b.As<Entity>().EntityName,
            Relation = r.As<IEnumerable<RelationshipInstance<Dictionary<string,string>>>>(),
        });
    
    var results = query.Results.ToList();
    
    foreach (var result in results)
    {
        foreach (var relationship in result.Relation)
        {
            if (relationship.TypeKey == "REL_TO")
            {
                var obj = JsonConvert.DeserializeObject<RelationshipObj>(JsonConvert.SerializeObject(relationship.Data));
                Console.WriteLine(obj.RelType);
            }
        }
    }
    

    We have to do a bit of a weird Deserialize/Serialize thing as we can't just use RelationshipObject<string> due to a constraint on the the generic part.