-
Notifications
You must be signed in to change notification settings - Fork 7
Routing, MK2
@samiwel, @SamGodwin2 and @jonnyshaw89 met to discuss. We think this schema will meet all of our known routing requirements going forward but there are a few questions we had surrounding how the expansion of routing rules will look in publisher that are probably worth considering separately.
It's recently come up that out current implementation of routing may not include enough complexity for our purposes meaning that it's time to make routing great again.
The new schema is designed to allow for more complex logic, more answer types, and even metadata. The schema below aims to allow for all these things while also making sure the front end receives the complex boolean logic in a simple way.
union ValueUnion = OptionIdArray | Custom | Answer | Metadata
union RoutingUnion = RoutingRule | RoutingRuleSet
union SubjectUnion = Answer | Metadata
enum OperatorEnum {
Equal
Not Equal
Greater Than
Less Than
Greater|Equal
Less|Equal
Contains All
Contains Some
Contains None
}
enum ConditionEnum {
AND
OR
}
enum RoutingRuleSetParent {
RoutingPage
RoutingRuleSet
}
type OptionIdArray {
options: [Option]
}
type RoutingPage {
routingRuleSets: [RoutingRuleSet]
fallThroughDestination: Destination
}
type RoutingRuleSet {
condition: ConditionEnum
rules: [RoutingUnion]
destination: Destination
}
type RoutingRule {
id: ID!
leftHandSide: SubjectUnion
operator: OperatorEnum
rightHandSide: ValueUnion
}
input CreateRoutingRule {
parentRoutingRuleSet: ID!
}
input UpdateRoutingRule {
id: ID!
leftHandSide: LeftHandSideInput
operator: OperatorEnum
rightHandSide: RightHAndSideInput
}
input LeftHandSideInput {
answerId: ID!
metadataId: ID!
}
input RightHandSideInput {
answerId: ID
metadataId: ID
optionIdArray: [ID]
customNumber: Int
customDate: Date
}
input DeleteRoutingRule {
id: ID!
}
input CreateRoutingRuleSet {
parentType: RoutingRuleSetParent!
parentId: ID!
}
input DeleteRoutingRuleSet{
id: ID!
This schema should hopefully allow the front end to receive a array which will be a combination of rules and rule sets. Each of the rule sets will allow further rules to be nested within them allowing for the complex nested queries we're looking for.
For example the rough structure of the returned data might be as follows:
{
condition: AND
rules: [
{
...RoutingRule
},
{
...RoutingRule
},
{
condition: OR,
rules: [
{
...RoutingRule
},
{
...RoutingRule
}
]
}
]
}
The idea being that the structure could go as deep as we'd like it to go.
The Query to retrieve this this data should hopefully look something like this:
Query RoutingRule (id: input){
RoutingRuleSet{
condition
rules {
... on RoutingRule {
leftHandSide
operator
rightHandSide
}
... on RoutingRuleSet {
condition
rules {
... on RoutingRule {
leftHandSide
operator
rightHandSide
}
... on RoutingRuleSet {
condition
rules {
... on RoutingRule {
leftHandSide
operator
rightHandSide
}
}
}
}
}
}
}
For the new database structure there would need to be another revamp:
Top
RoutigPageTable:
id | Pageid | destination |
---|---|---|
1 | FK | FK |
RoutingRuleSetTable:
id | Parent type | ParentId | comparator | destination |
---|---|---|---|---|
1 | enum | FK | AND or OR | FK |
RoutingRuleTable
id | Parent Id | LeftHandSideTable | RightHandSideTable | Operator |
---|---|---|---|---|
1 | FK | FK | FK | = or > ect... |
LeftHandSideTable (SubjectTable)
id | AnswerId | Metadata Id |
---|---|---|
1 | FK | FK |
RightHandSideTable (ValueTable)
id | AnswerId | Metadata Id | Custom | selectedType |
---|---|---|---|---|
1 | FK | FK | JSON | FK |
Option Table
id | optionId | RightHandSideTable id |
---|---|---|
1 | FK | FK |
For the rule (answer1 = optionNo || unanswered) and answer2 != 8 and answer3=optionYes
the following patten would emerge:
{
condition: AND
rules: [
{
condition: OR,
rules: [
{
lhs: answer1
comparator:Equal
rhs:option2
},
{
lhs: answer1
comparator:Not Set
rhs:null
}
]
},
{
lhs: answer2
comparator:NotEqual
rhs:option8
},
{
lhs: answer3
comparator:Equal
rhs:option1
}
]
}
The runner schema for this same condition currently looks like
[
{
goto: destination,
when: [
{
condition: "not set",
id: answer1
},
{
condition: "not equals",
id: answer2,
value: 8
},
{
condition: "not equals",
id: answer3,
value: option1
}
]
},
{
goto: destination,
when: [
{
condition: "equals",
id: answer1,
value: option2
},
{
condition: "not equals",
id: answer2,
value: 8
},
{
condition: "not equals",
id: answer3,
value: option1
}
]
}
];