Business Rule Problem

67 views
Skip to first unread message

Marc Lang

unread,
Nov 3, 2011, 3:53:45 PM11/3/11
to InterSystems: Ensemble in Healthcare
I have a question around an HL7 routing rule.

I think I am perhaps misunderstanding how to deal with repeating
segments.

For example, an ORU message may look like:

MSH|^~\&|LAB^H||||201107140044||ORU|17824284|T|2.1
PID|||1234567|1234567|MOUSE^MICKEY||19701210|M||||||||||123456789/11||
OBR||H1114070472Y|H,11.3151141.D|FBC||201107140010|201107140044|||||||
201107140034|Blood||||||||||C|||||||Passed by System checks
Oncall||||
OBX||ST|WBC^White Blood Count||7.3|x10^9/l|4.0-11.0||||20
NTE|1||
OBX||ST|RBC^Red Cell Count||5.11|x10^12/l|4.50-6.50||||20
NTE|1||
OBR||H1114070473|H,11.3151141.D|FBC||201107140010|201107140044|||||||
201107140034|Blood||||||||||C|||||||Passed by System checks
Oncall||||
OBX||ST|WBC^White Blood Count||7.3|x10^9/l|4.0-11.0||||20
NTE|1||
OBX||ST|RBC^Red Cell Count||5.11|x10^12/l|4.50-6.50||||20
NTE|1||

It's a custom version of HL7 2.1

I want a rule which looks at the OBR:2 field, and if ANY of them end
in a "Y", to route it to an appropriate target.

If my rule is:

"EndsWith(HL7.{PIDgrpgrp(1).ORCgrp(1).OBR:HISSORDERNO}, "Y")
= 1"

It works if the first OBR ends with a Y.

However, I need it to check all of the OBR:2 fields.
I assumed from the documentation that the below would work, but from
testing, this doesn't seem to be the case.

"EndsWith(HL7.{PIDgrpgrp(1).ORCgrp().OBR:HISSORDERNO}, "Y") =
1"

Any advice welcomed

kontreren

unread,
Nov 4, 2011, 2:39:31 PM11/4/11
to InterSystems: Ensemble in Healthcare
Would you not want the * (asterisk) inside the parends where you now
have ORCgrp(1)? So it is ORCgrp(*)?
Either that or loop through the group with a variable and put the
variable in the parends?
I'm pretty new to Ensemble so you would have to try it but I am fairly
sure someone told me * is for repetition and I know you can use
loops. Hope I'm not way out of context here but you did say "Any
advice welcome" :-) That includes "newbie advice" Best of luck.

Dale du Preez

unread,
Nov 4, 2011, 6:51:04 PM11/4/11
to ensemble-in...@googlegroups.com
I am hoping I can try to summarize the various responses so that we can straighten out what behaviours each approach is dealing with, as well as trying to capture a lot of Ted's previous emails on this sort of subject.

To start with, it's worth covering the three syntax options for segments paths.

The first approach is to use curly braces (i.e. {}) to indicate a full, schema-dependent path to a segment and property. You would use an expression like:
    HL7.{PIDgrpgrp(1).ORCgrp(1).OBR:HISSORDERNO}
This would return the value of the specific OBR segment at this path. In your case, this isn't helpful, but it's worth knowing that this is an option. Furthermore, when using the {} syntax, you can also use the "*" value at the end of an expression to return the count of segments in the expression. In our example above, the number of ORC groups in the first PID group would be given by the following expression:
    HL7.{PIDgrpgrp(1).ORCgrp(*)}
This sort of expression is often useful in DTL, where you may need to control loops based on the number of segments in a source document.

The second approach uses square braces (i.e. []) around the expression, and is meant to be a schema-independent segment lookup. In your case, the following path:
    HL7.[OBR:HISSORDERNO]
would return find the HISORDERNO value in all OBR segments present in the message, irrespective of where they appear. I'll discuss processing the return values shortly.

The third approach uses parentheses (i.e. ()) around the expression, and is a schema dependent lookup which may involve multiple segments. This comes closest to the functionality Marc is wanting, in that he wants to find values from all OBR segments in the PIDgrpgrp, which may be spread out all over the underlying HL7 message. The syntax in this case could be:
    HL7.(PIDgrpgrp(1).ORCgrp().OBR:HISSORDERNO)
Note that this will only return values inside OBR segments in the first PID group. Also, this () syntax is specific to the rules engine -- the functionality is available via the GetValues() API in the various virtual document classes.

But while this gets us a value, the processing of these values needs some thought. For the previous two approaches where multiple values can be returned from an expression, the rules engine will return the values wrapped in "<" and ">" characters as follows:
    <value1><value2><value3>
where the three strings in the message are "value1", "value2" and "value3", with wrapping "<" and ">" characters to distinguish each string. (There is some flexibility available for this functionality, but not from the rules engine at this stage.) Given the structure of this string, some care needs to be taken when performing comparisons against such an expression. As an example, the EndsWith() function will only look at the characters at the end of the string, which is not quite what you are looking for, because you want to match an incoming message where any OBR:2 ends in Y. Given the string format, you may want to use the following expression:
    "Contains(HL7.(PIDgrpgrp(1).ORCgrp().OBR:HISSORDERNO), "Y>")"
This checks whether the <>-delimited list contains "Y" at the end of one of the values. Note that Contains is case-sensitive, so you may want to add a ToUpper() or ToLower() conversion to make sure you catch both "y" and "Y" at the end of the strings.

I hope this helps AND proves helpful for others thinking about ways of getting at their message data.

Dale

Marc Lang

unread,
Nov 29, 2011, 5:52:17 AM11/29/11
to InterSystems: Ensemble in Healthcare
Hi Dale,

Finally got back to working on this project/functionality this
morning.

Your email is excellent, thanks for taking the time to explain it!

I will try and implement this today

On Nov 4, 10:51 pm, Dale du Preez <dale.dupr...@intersystems.com>
wrote:


> I am hoping I can try to summarize the various responses so that we can
> straighten out what behaviours each approach is dealing with, as well as
> trying to capture a lot of Ted's previous emails on this sort of subject.
>
> To start with, it's worth covering the three syntax options for segments
> paths.
>
> The first approach is to use curly braces (i.e. {}) to indicate a full,
> schema-dependent path to a segment and property. You would use an
> expression like:
>      HL7.{PIDgrpgrp(1).ORCgrp(1).OBR:HISSORDERNO}
> This would return the value of the specific OBR segment at this path. In
> your case, this isn't helpful, but it's worth knowing that this is an
> option. Furthermore, when using the {} syntax, you can also use the "*"
> value at the end of an expression to return the count of segments in the
> expression. In our example above, the number of ORC groups in the first
> PID group would be given by the following expression:
>      HL7.{PIDgrpgrp(1).ORCgrp(*)}
> This sort of expression is often useful in DTL, where you may need to
> control loops based on the number of segments in a source document.
>
> The second approach uses square braces (i.e. []) around the expression,
> and is meant to be a schema-independent segment lookup. In your case,
> the following path:
>      HL7.[OBR:HISSORDERNO]

> would return find the HISORDERNO value in *all* OBR segments present in

karthi

unread,
Mar 20, 2014, 1:45:01 PM3/20/14
to Ensemble-in...@googlegroups.com, ensemble-in...@googlegroups.com
Hi Dale,

You discussion is very informative, Can please elaborate this discussion on how to use if Strip and length functions to be used together.

For my case,

I need to remove Special characters like "(", ")", "-"  in a phone number sent from source HL7.(MFEgrp(1).STF:Phone().LocalNumber.PhoneNumber) and check the length is not equal to 10. (This is repeating field, I'm thinking I have mentioned correct syntax for repeating fields).

Thanks Very Much!!

-Karthi
Reply all
Reply to author
Forward
0 new messages