cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Rule engine path

Hi!

I want to design a rule engine in Neo4j.
One type of rule is a "inclusion 1-way". If a prameter is included in the input it can give you another parameter which in turn can give another parameter etc. Parameters is a global object and the same parameter can be used in many different rules.

In below example both P1 and P2 is needed for rule1 to be valid.

Rule1 gives P3 which in rule 2 gives P5 and P6. But to get P8 we also need P7 to be chosen.

How do I make a good query to traverse the graph.

2X_8_8e14e8467bafd8d482628cdc0aa8be85c0284ab5.jpeg

Script for creating above example

CREATE (p1:Param {id:"P1"})
CREATE (p2:Param {id:"P2"})
CREATE (p3:Param {id:"P3"})
CREATE (p4:Param {id:"P4"})
CREATE (p5:Param {id:"P5"})
CREATE (p6:Param {id:"P6"})
CREATE (p7:Param {id:"P7"})
CREATE (p8:Param {id:"P8"})
CREATE (p9:Param {id:"P9"})
CREATE (p10:Param {id:"P10"})
CREATE (r1:Regel {id:"REGEL1", type:"inclusion 1-way"})
CREATE (r1)-[:SELECT]->(p1)
CREATE (r1)-[:SELECT]->(p2)
CREATE (r1)-[:INCLUDE]->(p3)
CREATE (r1)-[:INCLUDE]->(p4)

CREATE (r2:Regel {id:"REGEL2", type:"inclusion 1-way"})
CREATE (r2)-[:SELECT]->(p3)
CREATE (r2)-[:INCLUDE]->(p5)
CREATE (r2)-[:INCLUDE]->(p6)

CREATE (r3:Regel {id:"REGEL3", type:"inclusion 1-way"})
CREATE (r3)-[:SELECT]->(p6)
CREATE (r3)-[:SELECT]->(p7)
CREATE (r3)-[:INCLUDE]->(p8)

This is what I've come up with so far for getting the first step

MATCH (p0:Param)<-[rel0:INCLUDE]-(r1:Regel)-[rel1:SELECT]->(p1:Param)
WHERE p1.id IN [ "P1","P2", "P7"] AND r1.type = "inclusion 1-way"
WITH (CASE WHEN COUNT(distinct p1)-SIZE((r1)-[:SELECT]-(:Param)) = 0 THEN 'ok' ELSE 'fel' END) AS check, r1.id AS rid, collect (distinct p0.id) AS incs
WHERE check = 'ok'
RETURN rid, incs

I would like it to return (regel1), P3,P4, (regel2), P5, P6, (regel3), P8 (even P8 since I have P7 as an input parameter).

1 REPLY 1

So I have created this tree out of the above rules.

MATCH (r:Regel)-[rel]-(p:Param)

WHERE r.type = "inclusion 1-way"

WITH r AS rule,

CASE WHEN type(rel) = "SELECT" THEN p.id ELSE null END AS selpars,

CASE WHEN type(rel) = "INCLUDE" THEN p.id ELSE null END AS incpars

ORDER BY selpars, incpars

WITH rule AS rule, COLLECT(incpars) AS incpars, COLLECT(selpars) AS selpars

UNWIND(incpars) as incpar

WITH rule, selpars, nodes(incpar)

MERGE (t1:TreeNode {id:selpars})

MERGE (t2:TreeNode {id:incpar})

MERGE (t1)-[:NEXT_INCLUDE]->(t2)

MERGE (t1)-[:IN_RULE]->(rule)

Will give me this graph

2X_a_a819698e767eaa4d9d23aeb113fa6c19aebb8375.png

If I have the in parameters P1,P2, P7 I should get P3, P4, P5, P6 and P8 (since P6,P7 implies P8).
How to write such a query?

If a add another node so that P4 implies P7. Then I will find P6 and P7 in the leafs which should imply that P8 should be included. How can I accomplish this?

CREATE (r4:Regel {id:"REGEL4", type:"inclusion 1-way"})
CREATE (r4)-[:SELECT]->(p4)
CREATE (r4)-[:INCLUDE]->(p7)

MATCH p=(t)-[r:NEXT_INCLUDE*]->() WHERE t.id = ["P1","P2"] RETURN p

╒═════════════════════════════════════════════════════════════╕
│"p" │
╞════════════════════════════════════════════════════════════╡
│[{"id":["P1","P2"]},{},{"id":["P3"]}] │
├────────────────────────────────────────────────────────────┤
│[{"id":["P1","P2"]},{},{"id":["P3"]},{"id":["P3"]},{},{"id":["P5"]}]│
├────────────────────────────────────────────────────────────┤
│[{"id":["P1","P2"]},{},{"id":["P3"]},{"id":["P3"]},{},{"id":["P6"]}]│
├────────────────────────────────────────────────────────────┤
│[{"id":["P1","P2"]},{},{"id":["P4"]}] │
├────────────────────────────────────────────────────────────┤
│[{"id":["P1","P2"]},{},{"id":["P4"]},{"id":["P4"]},{},{"id":["P7"]}]│
└────────────────────────────────────────────────────────────┘