I have a role based application and 2 nodes Role
and Cartable
and i am managing my permissions by creating a relation between these 2 nodes, if a relationship exists between these two nodes means this role has a permission for example to view the Cartable:
client.Cypher
.Merge("(s:SiteConfiguration)-[:"
+ Relations.ROLE_IN_SITE.ToString()+ "]-(r:Role)-[r1:"
+ Relations.ROLE_HAS_CARTABLE.ToString() + "]->(ca:Cartable)")
.Where("r.Id = {param}").WithParam("param", roleId)
.AndWhere("ca.Id= {param1}").WithParam("param1", cartableId)
.AndWhere("s.SiteId= {param2}").WithParam("param2", MvcApplication.SiteConfigurations.Base.SiteId)
.CreateUnique("(r)-[:" + Relations.EDIT_COMMENT.ToString()+"]-(ca)")
.ExecuteWithoutResults();
Now i want to check if relation exists between two nodes and return a Boolean based on that so i wrote this:
var q = new CypherFluentQuery(client) as ICypherFluentQuery;
q = q.Match("(s:SiteConfiguration)-[:"
+ Relations.ROLE_IN_SITE.ToString() + "]-(r:Role)-[r1:"
+ Relations.VIEW_CARTABLE.ToString() + "]-(c:Cartable)");
q = q.Where("s.SiteId= {param}").WithParam("param", MvcApplication.SiteConfigurations.Base.SiteId);
q = q.AndWhere("r.Id= {param1}").WithParam("param1", roleId);
q = q.AndWhere("c.Id= {param2}").WithParam("param2", cartableId);
But I'm not sure what i should return here, since VIEW_CARTABLE
doesn't have any values as anonymous object on the relationship. so my question is how to check if a certain relationship exists between these two nodes?
Because you are using a MATCH
- you won't get any results if r1
is not there. If you know you're going to get (s)-->(r)
- but not sure about (r)-->(c)
then you need to go OPTIONAL
.
For example (using the :play Movies
db):
var query = gc.Cypher
.Match("(p:Person {name:'Julia Roberts'})")
.OptionalMatch("(p)-[r]->(m:Movie)")
.Where("m.title = 'The Green Mile'")
.Return((p, m) => new
{
Person = p.As<Person>(),
Movie = m.As<Movie>(),
IsInMovie = Return.As<bool>("NOT (r IS NULL)")
});
Here I look for a person (Julia Roberts) and then try to see if she has a relationship to a given movie - in this case to one I know she's not in.
I use an OptionalMatch
to do this, and then check if r
is null.
Now, in practice - I don't need to know about r
, as if there is no link to the movie, m
will be null
.
In your case, you'd switch the top to be:
var q = new CypherFluentQuery(client)
.Match("(s:SiteConfiguration)-[:ROLE_IN_SITE]-(r:Role)")
.OptionalMatch("(r)-[r1:VIEW_CARTABLE]-(c:Cartable)")
.Where("s.SiteId= {param}").WithParam("param", MvcApplication.SiteConfigurations.Base.SiteId)
.AndWhere("r.Id= {param1}").WithParam("param1", roleId)
.AndWhere("c.Id= {param2}").WithParam("param2", cartableId)
.Return((s,r,c,r1) => new {
Site = s.As<SiteConfiguration>(),
Role = r.As<Role>(),
Cartable = c.As<Cartable>(),
IsCartable = Return.As<bool>("NOT (r1 IS NULL)")
});
And you can either check if IsCartable
is true
or if Cartable == null