Understanding router snap's functionality

Hi Team,

I wanted to understand more about Router snap as I was stuck routing data today. Let’s assume I’m reading a flat file with 100 records and the file has 3 columns, ID (can have duplicates), Name, and Phone Number.

I want to route the data where ID = 130 and rest others, how do I achieve this?
As I want both the data for different transformations, can’t use a filter snap and that’s where router helps.

The first condition would look like $ID == 130, what would the other condition look like to consider all the remaining records.

I don’t want to write $ID !=130; reason being, my actual use case has a lot of conditions, so I want either 100 or others. I did try with true and false but it didn’t seem to work for me.

In addition to this, I wanted to learn whether we can write a nested condition in router, e.g.
$Name == null || $PhoneNumber== null || $Name == null && $PhoneNumber== null
Would the above work as expected?

Expectation is:

Route all records whose Name is Null OR Phone Number is Null OR both Name & Phone Number is Null

Appreciate your help and time on this one.

Regards,
Darsh

I’m assuming that you want records that have ID==130 to take first route, and all others should take the second route. I’ve illustrated a short example in the pic below. Take note of the “First Match” checkbox. In this example, the expressions will be evaluated sequentially from top to bottom. If ID==130 is true, then the record will be routed to the 130 output view. Subsequent expressions will not be evaluated. If the ID!=130, since a hard coded true value is in the next expression, the record will be routed to the “all others” output view.

Here’s the concept behind the “First Match” checkbox. If the “First Match” checkbox is turned on, once a true expression has been found, then the snap will complete without evaluating the remaining expressions. If the “First Match” checkbox is turned off, all expressions will be evaluated and the record will be routed to all output views that have expressions that result in a true result.

Regarding your last question about using the || and && operators in your expression, yes, that is valid. I will note that you should also use parenthesis to clarify your orders of operation.

I feel you wanted something like this (which everything between the parenthesis seems superfluous given the 2 preceding OR expressions):
$Name == null || $PhoneNumber== null || ($Name == null && $PhoneNumber== null)

Hope this info helps.

image

1 Like

Thank you @alex.panganiban.guild for your suggestions.
I wasn’t using first match when I kept the expression as “true”, I will try this solution and keep you posted on how it goes.

One thing I didn’t understand was the rationale behind using first match. As per your detailed explanation,

If the “First Match” checkbox is turned on, once a true expression has been found, then the snap will complete without evaluating the remaining expressions.

If the “First Match” checkbox is turned off, all expressions will be evaluated and the record will be routed to all output views that have expressions that result in a true result.

If first match is not going to evaluate the remaining expressions, why do we need to use it?

Thank you so much for clarifying on the nested condition, I will use the parenthesis as a differentiator.

“If first match is not going to evaluate the remaining expressions, why do we need to use it?”

The reason one may need something like this, is that they may wish that a record be exclusive to only 1 output view.

Gotcha but would it suffice my use case where I need one route to have ID==130 and other route to have the remaning?

In that case, I would definitely use the ‘first match’ feature. this way the ID=130 records won’t also go into the ‘all others’ output view as well.

@darshthakkar, look at it this way.
The router is sort of like a chain of ‘IF’ statements.
Without “first match”, it’s like multiple “if’s” in a row, so that sending a document down the first Route doesn’t preclude routing it to, say, the third Route…

if ( $doc.lastName == "Munster" || $doc.lastName == "Kolchak" )
    route_to_path(doc, "Monster shows");
if ( $doc.lastName == "Kirk" )
    route_to_path(doc, "SF shows");
if ( $doc.lastName == "Munster" || $doc.lastName == "Seinfeld" )
    route_to_path(doc, "Comedy shows");

In the pseudocode above, if doc.lastName is “Munster”, a copy of the doc will be routed to both the “Monster shows” path and the “Comedy shows” path.


Now, by turning on “First match”, you tell it “route the document only down the first Route where the Expression is true. Stop there and don’t route that document down other routes. If no route’s expression is true, just dump the document into the void.”

That’s like putting an “ELSE” in front of each of the “IF” statements except the first.

if ( $doc.lastName == "Munster" || $doc.lastName == "Kolchak" )
    route_to_path(doc, "Monster shows");
else if ( $doc.lastName == "Kirk" )
    route_to_path(doc, "SF shows");
else if ( $doc.lastName == "Munster" || $doc.lastName == "Seinfeld" )
    route_to_path(doc, "Comedy shows");

If doc.lastName is “Munster” it will route to “Monster shows” and nothing else. It will never get to case number 3. If doc.lastName is “Forbin” it won’t match any of the expressions, and the doc won’t be routed anywhere – it will just evaporate.


Okay, so why does @alex.panganiban.guild recommend using “First match” and setting the last item to “true”? Can’t we just say $ID == 130 and $ID != 130 ??

Well, we can. But we’d rather not.

To see why, convert it to pseudocode again:

if ( $ID == 130 )
    route_to_path(doc, "130 path");
if ( $ID != 130 )
    route_to_path(doc, "Everything else path");

That works fine.

Then some other developer comes along and sees that the values “42” and “153” also need special processing. Let’s say they’re OCD and they put everything in numerical order:

if ( $ID == 42 )
    route_to_path(doc, "42 path");
if ( $ID == 130 )
    route_to_path(doc, "130 path");
if ( $ID == 153 )
    route_to_path(doc, "153 path");
if ( $ID != 130 )
    route_to_path(doc, "Everything else path");

Whoops! ID’s 42 and 153 continue to be routed down the “Everything else” path in addition to their own new paths.

Now, let’s turn on “First match” and lets put the last expression as simply true.
We get:

if ( $ID == 42 )
    route_to_path(doc, "42 path");
else if ( $ID == 130 )
    route_to_path(doc, "130 path");
else if ( $ID == 153 )
    route_to_path(doc, "153 path");
else if ( true )
    route_to_path(doc, "Everything else path");

This does what we want, and avoids future bugs when the snap gets changed.
And else if ( true ) is just a different way of saying else.


You do not want “First match” if you need to route the same document down multiple paths. For a contrived example, suppose the documents refer to people, and you have special processing of one type for married-vs-single, and some other kind of processing for male-vs-female. That’s 4 different routes, and a copy of each doc will always be routed down exactly two of those paths (assuming all docs are only male/female and married/single).

Hope this helps!

1 Like

Thank you @ForbinCSD for the detailed explanation. It was super helpful. I now understand the importance of “First Match” as well as how ordering of the conditions in router is so vital.

Thank you again for your help. @alex.panganiban.guild also deserves the credit behind this solution so THANK YOU @alex.panganiban.guild .

Closing this thread now.

1 Like