MATCH (post: Post)<-[postRule:POST_RULE]-(rule: Rule)
<-[catRule: RULE_CATEGORY]-(category:Category)
RETURN post, category
Post has many rules
Rules have many categories
I have an array of allowed categoryIds.
How would I return only the posts that has atleast 1 category per rule of the post?
Graph looks like this:
Red is the post.
Blue is rules (4) of them
Yellow (or brown idk) are categories.
I need my array to match at least 1 yellow one for each blue one
Can you write an example of what you want to return? and the properties required
At the moment, I can propose you:
MATCH (post: Post)<-[:POST_RULE]-(rule: Rule)
WITH post, rule
CALL apoc.cypher.run('MATCH (rule)<-[catRule: RULE_CATEGORY]-(category:Category) RETURN post, rule, category LIMIT 1', {post:post, rule:rule})
YIELD value
RETURN value.post AS post, value.rule AS rule, value.category AS category
I only want to return allowed posts that I have permission for.
So I have an array of allowed categories. ['TEACHER', 'TOPICS', 'SCHOOL', 'GRADE']
Check screenshot above.
Now If I pass that array, I can return the post. ( Because my post ( text2) has 4 rules with 1 category connected to each of the rules.
If I were to pass allowed categories ['TEACHER', 'TOPICS', 'SCHOOL'],
I wouldn't be able to get the post, because I don't match the rule that has only grade connected to it.
So in my allowed categories, I need at least 1 category for each of the rules connected to all the posts.
I hope I made it a bit clearer, Thank you in advance
Properties of POST node are not important, since they are not used in the rules,
Properties of relationship :POST_RULE are empty, no properties, just the connection
Properties of a node RULE is just that UUID in the screenshot, so it's unique, but I won't be using it ( essentially no properties )
Relationship :RULE_CATEGORY doesn't have properties as well
Category has a property "name" and that's the only propery.
I will be passing parameter called "allowedCategories" which is an array of allowed category names
( ['TEACHER', 'PARENT', 'SCHOOL'] ) and I need at least 1 category for every rule per post to return a post.
MATCH (post:Post)<-[:POST_RULE]-(rule:Rule)<-[:RULE_CATEGORY]-(category:Category)
WITH post, rule, collect(DISTINCT category.name) AS categories
WHERE any(x IN categories WHERE x IN $allowedCategories)
RETURN post
Closer, but keep in mind, that RULE node can have multiple categories. There you are matching all categories belonging to the post.
I am sorry, screen shot is confusing because it doesn't have multiple categories connected to it
I am sorry, I hit the wrong reply thread button and made things even more confusing . But I read your query..my response was meant for your last one with ALL function inside of it. You check every category of the post and see if I have every category, but I need at least 1 per rule and rule can have multiple categories.
Check this one.
In order to return text4 I need category PARENT and SCHOOL and TOPICS and (GRADE1 OR GRADE3). Bottom blue one has 2 different grades. So either is good, but I need at least 1 per BLUE node.
With any I would need PARENT OR SCHOOL OR TOPIS OR GRADE1 OR GRADE3
It is combination of AND and ORS. Per BLUE at least 1 Yellow.
This query will check if all rules have at least one allowed categories in $allowedCategories
MATCH (post:Post)<-[:POST_RULE]-(rule:Rule)<-[:RULE_CATEGORY]-(category:Category)
WITH post, rule, collect(DISTINCT category.name) AS categories
WITH post, collect(categories) AS rule_cats
WHERE all(x IN rule_cats WHERE any(n IN x WHERE n IN $allowedCategories))
RETURN post
Jesus I think it seems to be working...
Can you walk me trough the process.. I got lost.. I mean you seem to be double collecting, but how does it know you are nesting PER RULE? Why as "rule_cats"?
How does it know? It can't be because rule is defined in the "WITH" before categories..can it?
WITH post, rule, collect(DISTINCT category.name) AS categories will return:
post1, rule1, ['PARENT']
post1, rule2, ['SCHOOL']
post1, rule3, ['TOPICS']
post1, rule4, ['GRADE1', 'GRADE3']
WITH post, collect(categories) AS rule_cats will return:
post1, [['PARENT'], ['SCHOOL'], ['TOPICS'], ['GRADE1', 'GRADE3']]
WHERE all(x IN rule_cats WHERE any(n IN x WHERE n IN $allowedCategories)) will check for each element of rule_cats if at least one of the category is in $allowedCategories