How to use aliases to represent collections
- Last Updated: May 9, 2022
- 8 minute read
- Corticon.js
- Documentation
Aliases provide a means of using scope to specify elements of a collection; more specifically, you use aliases (expressed or declared in the Scope section of the Rulesheet) to represent copies of collections. This concept is important because aliases give you the ability to operate on and compare multiple collections, or even multiple instances of the same collection. There are situations where such operations and comparisons are required by business rules. Such rules are not easy (and sometimes not possible) to implement without using aliases.
For the purposes of illustration, a new scenario and business Vocabulary will be used. This new scenario involves a financial services company that compares and ranks stocks based on the values of attributes such as closing price and volume. A model for doing this kind of ranking can get very complex in real life; however, this example is kept simple. The new Vocabulary is illustrated:
This Vocabulary consists of only two entities:
Security: Represents a security (stock)
with attributes like security name (secName), ticker symbol, and rating.
SecInfo: Is designed to record information
for each stock for each business day (busDay); attributes
include values recorded for each stock (closePrice and
volume) and values determined by rules (totalWeight and rank) each
business day.
The association between Security and
SecInfo is 1..*
(one-to-many) because there are multiple instances of SecInfo data (multiple days of historical data) for each Security.
In this scenario, three rules determine a security's rank:
![]()
Finally, rules are used to assign a rank based on the total weight. It is
interesting to note that although the rules refer to a security's closing price, volume,
and rule weights, these attributes are actually properties of the SecInfo entity. The Rulesheet that accomplishes these tasks is this:
In the preceding figure, two business rules are expressed in a total of
four rule models (one for each possible outcome of the two business rules). The rules are
straightforward, but the shortcuts (alias values) used in these rules are different than
other rules you have seen. In the Scope section, you see that Security is the scope for the Rulesheet, which is not a new concept. But then,
there are two aliases for the SecInfo entities associated
with Security: secinfo1
and secinfo2. Each of these aliases represents a separate but identical collection of the SecInfo entities associated with Security. In
this Rulesheet, you constrain each alias by using filters. In a later example, you will see
how more loosely constrained aliases can represent many different elements in a collection
when the rules engine evaluates rules. In this example, though, one instance of SecInfo represents the close of the current business day
(now), and the other instance represents the close of
the previous business day (now.addDays(-1).)
.addDays operator, see that topic in the Rule Language Guide.After the aliases are created and constrained, you can use them in your
rules where needed. In the figure Rulesheet with Ranking Model Rules 1
and 2, you see that the use of aliases in the Conditions
section allows comparison of closePrice and volume values from one specific SecInfo element (the one with today's date) of the collection with another
(the one with yesterday's date).
The following figure shows a second Rulesheet that uses a nonconditional
rule to calculate the sum of the partial weights from the model rules determined in the
first Rulesheet, and conditional rules to assign a rank value between 1 and 4 to each
security based on the sum of the partial weights. Because you are only dealing with data
from the current day in this Rulesheet (as specified in the filters), only one instance of
SecInfo per Security
applies, and we do not need to use aliases.
You can test your new rules using a Ruleflow to combine the two Rulesheets. In a Ruletest that executes the Ruleflow, you expect to see the following results:
- The
Security.secInfocollection that contains data for the current business day (the expectation is that this collection reduces to a singlesecinfoelement, because only onesecinfoelement exists for each day) should be assigned to aliassecinfo1for evaluating the model rules. - The
SecInfoinstance that contains data for the previous business day (again, the collection filters to a singlesecinfoelement for eachSecurity) should be assigned to aliassecinfo2for evaluating the model rules. - The partial weights for each rule, sum of partial weights, and
resulting rank value should be assigned to the appropriate attributes in the current
business day's
SecInfoelement.
A Ruleflow constructed for testing the ranking model rules is as shown:
Security object and three
associated SecInfo objects were added from the
Vocabulary. The current day at the time of the Ruletest is 11/12/2020, so the three SecInfo objects
represent the current business day and two previous business days. The third business day
is included in this Ruletest to verify that the rules are using only the current and
previous business days. None of the data from the third business day should be used if the
rules are executing correctly. Based on the values of closePrice and volume in the two SecInfo objects being tested, you expect to see the highest
rank of 4 assigned to your security in the current business day's SecInfo object.Both closePrice and volume
were higher than the values for those same
attributes; therefore, both rule1Weight and rule2Weight attributes were
assigned their high values by the rules. Accordingly, the totalWeight value calculated from the sum of the partial weights was the
highest possible value, and a rank of 4 was assigned to this security for the current day.
As previously mentioned, the preceding example was tightly constrained in that the aliases were assigned to two specific elements of the referenced collections. What about the case where there are multiple instances of an entity that you would like to evaluate with your rules?
The second example is also based on the security ranking scenario, but, in
this example, the rank assignment that was accomplished will be done in a different way.
Instead, you will rank a number of securities based on their relative performance to one
another, rather than against a preset ranking scheme. In the rules for the new example, you
compare the totalWeight value that is determined for each
security for the current business day against the totalWeight of every other security, and determine a rank based on this comparison of totalWeight
values. A Rulesheet for this alternate method of ranking securities is shown in the next
figure.
In these new ranking rules, aliases were created to represent specific
instances of Security and their associated collections of
SecInfo. As in the previous example, filters constrain
the aliases, most notably in the case of the SecInfo
instances, where secInfo1 and secInfo2 are filtered for a specific value of busDay (today's date). However, our Security
instances were loosely constrained. You have a filter that prevents the same element of
Security from being compared to itself (when sec1 = sec2 ). No other
constraints are placed on the Security aliases.
Security
are not assigned to our aliases. Instead, the rules engine is instructed to evaluate all allowable combinations (that is, all those combinations that
satisfy the first filter) of Security elements in the
collection in each of the aliases (sec1 and sec2). For each allowable combination of Security elements, the totalWeight values from the associated SecInfo element for busDay = now are
compared, and increment the rank value for the first SecInfo element (secinfo1) by 1 if its
totalWeight is greater than that of the second SecInfo object (secinfo2).
The end result should be the relative performance ranking of each security.
Security elements and an associated secInfo element for each were added. Note that each alias
represents all
security elements and their associated secInfo elements. The current day at the time of the Ruletest
is 5/7/2022, so each Security.secInfo.busDay attribute is
given the value of 5/7/2022 (if additional secinfo
elements in each collection were added, they would have earlier dates, and therefore would
be filtered out by the preconditions on each alias). Each Security.secInfo.rank was initially set equal to 1 so that the lowest ranked
security still has a value of 1. The lowest ranked security is the one that loses all
comparisons with the other securities. In other words, its weight is less than the weights
of all other securities. If a security's weight is less than all the other security
weights, its rank will never be incremented by the rule, so its rank will remain 1. The
values of totalWeight for the SecInfo objects are all different; therefore, each security ranked between 1
and 4 with no identical rank values is expected.Security.secInfo elements (multiple securities) with the
same totalWeight value for the same day, then the
final rank assigned to these objects is expected to be
the same as well. Further, if there were multiple Security.secInfo entities sharing the highest relative totalWeight value in a given Ruletest, then the highest
rank value possible for that Ruletest would be
lower than the number of securities being ranked, assuming all rank values are initialized at 1. the Ruletest results are as expected. The security
with the highest relative totalWeight value ends the
Ruletest with the highest rank value after all rule
evaluation is complete. The other securities are also assigned rank values based on the relative ranking of their totalWeight values. The individual rule firings that resulted in these
outcomes are highlighted in the message section at the bottom of the results sheet.
It is interesting to note that nowhere in the rules is it stated how many security entities will be evaluated. This is another example of the ability of the declarative approach to produce the intended outcome without requiring explicit, procedural instructions.