Other Options
This page describes how to use other options for Business Intelligence cubes and subject areas.
Also see Accessing the BI Samples.
Specifying maxFacts in the Cube Definition
While you are developing a cube, you typically recompile and rebuild it frequently. If you are using a large data set, you might want to limit the number of facts in the fact table, in order to force the cube to be rebuilt more quickly. To do this, you can specify the pMaxFacts argument for %BuildCube(); see Building the Cube in the Terminal.
Or you can specify the maxFacts attribute as follows:
-
In an IDE, open the cube class.
-
Find the <cube> element:
<cube name="HoleFoods" caption="HoleFoods Sales" defaultListing="Listing" nullReplacement="Missing Value" actionClass="HoleFoods.KPIAction" sourceClass="HoleFoods.Transaction">
-
Add the maxFacts attribute to this element:
<cube name="HoleFoods" caption="HoleFoods Sales" defaultListing="Listing" nullReplacement="Missing Value" actionClass="HoleFoods.KPIAction" sourceClass="HoleFoods.Transaction" maxFacts="10000">
The value that you specify determines the maximum size of the fact table.
-
Save and recompile the class.
-
Rebuild the cube.
Be sure to remove the maxFacts attribute before you deploy the cube.
Restricting the Records Used in the Cube
By default, the system uses all the records in the source class. You can modify the cube definition so that some of the records are ignored. You can do this in either or both of the following ways:
-
By specifying the Build restriction option for the cube definition, as described in Defining Models for InterSystems Business Intelligence.
This option has no effect if the cube is based on a data connector.
-
By defining the %OnProcessFact() callback of the cube class.
%OnProcessFact() Callback
To ignore some of the records of the base table and not include them in the cube, you can define the %OnProcessFact() method in your cube definition class:
classmethod %OnProcessFact(pID As %String, ByRef pFacts As %String, Output pSkip As %Boolean, pInsert As %Boolean) as %Status
The system calls this method immediately after accessing each row in the base table, when building or updating the fact table. It passes the following values to this method:
-
pID is the ID of the row in the source data being processed.
-
pFacts is a multidimensional array that contains the values that will be used for the row. This array has the following structure:
Node Value pFacts(factName) where factName is the name of the level or measure in the fact table, as specified by the Field name in fact table option. Value of that level or measure. For example, Magnolia or 47. -
pInsert is 1 if this is a new row.
If you want to skip this record, your method should set pSkip to true; otherwise it should set pSkip to false.
For example, the following callback causes the cube to ignore all patients whose favorite color is blue:
ClassMethod %OnProcessFact(pID As %String, ByRef pFacts As %String,
Output pSkip As %Boolean, pInsert As %Boolean) As %Status
{
if pFacts("DxColor")="Blue"
{
set pSkip=1
} else {
set pSkip=0
}
quit $$$OK
}
This example assumes that the cube defines the Field name in fact table option as DxColor for the favorite color level.
If your %OnProcessFact() evaluates records based on the levels or measures you specify using the pFacts array, you must include the corresponding cube elements whenever you perform a Selective Build for the cube. In the preceding example, the user must include DxColor in any Selective Build for the cube. Otherwise, every record will yield an error because the value of pFacts(“DxColor”) will be undefined.
For another example, the following callback would cause the cube to ignore all records whose ID was less than 1000000:
ClassMethod %OnProcessFact(pID As %String, ByRef pFacts As %String,
Output pSkip As %Boolean, pInsert As %Boolean) As %Status
{
if pID<1000000
{
set pSkip=1
} else {
set pSkip=0
}
quit $$$OK
}
Manually Specifying the Members for a Level
After you define a level in the Architect, you can manually specify the members and their order. To do so, modify the cube class in an IDE as follows:
-
In an IDE, open the cube class.
-
Find the section that defines the level:
<level name="MyLevel" displayName="MyLevel" ... > </level>
-
Just before the </level> line, add a set of <member> elements like the following:
<level name="MyLevel" displayName="MyLevel" ... > <member name="first" displayName="first" spec="1" /> <member name="second" displayName="second" spec="2" /> <member name="third" displayName="third" spec="3" /> <member name="fourth" displayName="fourth" spec="4" /> <member name="fifth" displayName="fifth" spec="5" /> </level>
Each <member> element identifies a member. In <member>, name specifies the name of the member, displayName specifies an optional localized display name for the member, and spec specifies an optional key specification for this member.
The rules for name and spec are as follows:
Scenario Requirement Result Specify only name The value of name must exactly match a value of the source property or source expression, including case. The value of name becomes the key. Specify both name and spec The value of spec must exactly match a value of the source property or source expression, including case. The value of spec becomes the key. Additional notes:
-
In these attributes, you cannot use XML reserved characters. See the following subsection.
-
Include as many <member> elements as needed.
-
The order of these elements determines the default sort order of the corresponding members.
-
Include all members of the level (there is no wildcard option).
-
A <member> cannot have the same name as a <property> within the same level.
-
-
Save and recompile the class.
-
Rebuild the cube or perform a selective build of the level.
This option is useful only when the set of members is unlikely to change. If the system receives new records that contain a value not given by one of the <member> elements, those records are not represented in this level.
XML Reserved Characters
When you edit a cube class in an IDE, you cannot use XML reserved characters in the values of name, displayName, or other attribute values. Instead substitute as follows:
Reserved Character | Use This Instead |
---|---|
< | < |
& | & |
" | " |
' | ' |
It is not an error to use >, but you can use > instead of that character.
When you type these characters into input fields in the Architect, the Architect automatically makes these substitutions. If you examine a cube class in an IDE, you might notice that the Architect also makes other substitutions. The preceding table lists only the substitutions that are necessary.
Adding Custom Indexes to the Fact Table
The system automatically defines all the indexes that it needs. However, you can use the fact table directly for your own purposes, and if you do, you might need additional indexes. To add them, edit the cube class in an IDE and add <index> elements as needed.
Customizing Other Cube Callbacks
The class %DeepSee.CubeDefinitionOpens in a new tab provides callback methods that you can override to customize the cube behavior further. This section describes some commonly overridden methods.
Also see %OnProcessFact() Callback and Filtering a Cube or Subject Area Dynamically, elsewhere in this page.
See the class reference for %DeepSee.CubeDefinitionOpens in a new tab for additional options.
%OnAfterProcessFact() Callback
The %OnAfterProcessFact() callback enables you to add custom code that runs after any given record is added or updated in the fact table of the cube.
ClassMethod %OnAfterProcessFact(pID As %String, ByRef pFactArray As %String, pUpdateStatus As %Status) as %Status
The system passes the following information to this callback:
-
pID is the id of the row in the source data being processed.
-
pFacts is an array containing the values that will be used for the row, subscripted by fact name.
-
pUpdateStatus is the status about to be returned by %ProcessFact(). If an error is passed in, this error will already be logged in the Business Intelligence logs and the ^DeepSee.BuildErrors global.
The %ProcessFact() method ignores the value returned by this method.
%OnGetDefaultListing() Callback
The %OnGetDefaultListing() callback enables you to programmatically specify the name of the listing to use, in the case where the system uses the default listing. The signature of this method is as follows:
ClassMethod %OnGetDefaultListing() as %String
This callback is called when a user requests the default listing and has no effect when a specific listing is requested. The following shows an example:
ClassMethod %OnGetDefaultListing() As %String { Quit "Listing By Product" }
You could use this, for example, to check the role to which a user belongs and display a suitable listing for that role.
%OnExecuteListing() Callback
In some cases, additional setup work is required before a listing query can run.
To do this, implement the %OnExecuteListing() method in your cube definition class:
ClassMethod %OnExecuteListing(pSQL As %String) as %Status
The system calls this method immediately before it executes a listing query. When the system calls this method, it passes the value pSQL, which is the listing query that will be executed.
%OnAfterBuildCube() Callback
The %OnAfterBuildCube() callback, if defined, is called after the cube is built.
ClassMethod %OnAfterBuildCube(pBuildStatus As %Status, pBuildErrors As %Boolean = 0) As %Status
The system calls this as the last step in the %BuildCube method in %DeepSee.UtilsOpens in a new tab. The system passes the following information to this callback:
-
buildStatus is the status of the cube build thus far
-
factErrorCount is the count of any facts for which there were build errors.
Your implementation should return an instance of %StatusOpens in a new tab.
This method is called before the lock on the cube build is released, which means that only one process can execute the callback at once.
Filtering a Cube or Subject Area Dynamically
Instead of (or in addition to) specifying a hardcoded filter for a subject area, you can implement the %OnGetFilterSpec() callback. This enables you to specify the contents of the filter at runtime. This callback is also available in cube classes. Thus you can filter both cubes and subject areas dynamically.
The signature of this method is as follows:
classmethod %OnGetFilterSpec(pFilterSpec As %String) as %String
Here pFilterSpec is the value of the filterSpec attribute in <subjectArea>. The method must return a valid MDX set expression. For example:
ClassMethod %OnGetFilterSpec(pFilterSpec As %String) As %String
{
Quit "AgeD.H1.[20 to 29]"
}
The following shows another simple example. In this case, the method checks the $ROLES special variable and removes any filtering if the user belongs to the %All role:
ClassMethod %OnGetFilterSpec(pFilterSpec As %String) As %String
{
if $ROLES["%All" {
//remove any filtering
set pFilterSpec=""
}
Quit pFilterSpec
}
For another example, the following callback modifies the original filter value by performing a cross join of the original value and an additional filter:
ClassMethod %OnGetFilterSpec(pFilterSpec As %String) As %String
{
//test to see if $ROLES special variable includes TestRole
if $ROLES["%DB_SAMPLE" {
//a member expression like the following is a simple set expression
set colorrestrict="colord.h1.[favorite color].red"
//create a tuple that intersects the old filter with the new filter
//this syntax assumes original is just a member
set newfilter="CROSSJOIN("_pFilterSpec_","_colorrestrict_")"
set pFilterSpec=newfilter
}
Quit pFilterSpec
}