cancel
Showing results forย 
Search instead forย 
Did you mean:ย 

Understanding router snap's functionality

darshthakkar
Valued Contributor

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

1 ACCEPTED SOLUTION

ForbinCSD
Contributor

@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!

View solution in original post

7 REPLIES 7

alex_panganiban
Contributor

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

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.

alex_panganiban
Contributor

โ€œ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?