Custom query instance nodes specification
TypeScript type: CustomQueryInstanceNodesSpecification.
Returns nodes for instances returned by a provided ECSQL query.
Attributes
Name | Required? | Type | Default |
---|---|---|---|
Filtering | |||
queries |
No | QuerySpecification[] |
[] |
hideNodesInHierarchy |
No | boolean |
false |
hideIfNoChildren |
No | boolean |
false |
hideExpression |
No | ECExpression | "" |
suppressSimilarAncestorsCheck |
No | boolean |
false |
Ordering | |||
priority |
No | number |
1000 |
doNotSort |
No | boolean |
false |
Grouping | |||
groupByClass |
No | boolean |
true |
groupByLabel |
No | boolean |
true |
Misc. | |||
hasChildren |
No | "Always" | "Never" | "Unknown" |
"Unknown" |
relatedInstances |
No | RelatedInstanceSpecification[] |
[] |
nestedRules |
No | ChildNodeRule[] |
[] |
Attribute: queries
Specifications of queries used to create the content. Query specifications define the actual results of the specification. There are 2 types of supported query specifications:
The queries used in the specifications must return ECClassId
and ECInstanceId
columns, e.g.:
SELECT e.ECClassId, e.ECInstanceId FROM bis.Element e WHERE e.Parent.Id = 0x123
Note: sorting and grouping happens after results of multiple query specifications are aggregated.
Type | QuerySpecification[] |
Is Required | No |
Default Value | [] |
String query specification
The specification contains an ECSQL query which is used to query for instances.
Name | Required? | Type | Meaning |
---|---|---|---|
query |
Yes | string |
Specifies the search ECSQL query. |
class |
Yes | SingleSchemaClassSpecification |
Specification of ECClass whose instances the query returns. The specification may also point to a base class of instances returned by the query. If the query returns instances that are not of this class, they aren't included in the result set. |
// The ruleset has a root nodes' specification that uses a given query to get all `bis.Model` instances.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "CustomQueryInstanceNodes",
queries: [
{
specType: "String",
class: { schemaName: "BisCore", className: "Model" },
query: `SELECT * FROM bis.Model`,
},
],
},
],
},
],
};
ECProperty value query specification
The specification specifies the name of the parent node instance property whose value is the ECSQL used to query for instances.
Precondition: can be used only if parent node is ECInstance node. If there is no immediate parent instance node, the rules engine walks up the hierarchy until it finds one. If that fails, this specification has no effect.
Name | Required? | Type | Meaning |
---|---|---|---|
parentPropertyName |
Yes | string |
Specifies name of the parent instance property whose value contains the ECSQL query. Warning: the property whose name is specified must be of string type. |
class |
Yes | SingleSchemaClassSpecification |
Specification of ECClass whose instances the query returns. The specification may also point to a base class of instances returned by the query. If the query returns instances that are not of this class, they aren't included in the result set. |
// The ruleset has a root nodes' specification that returns `MyDomain.MyParentElement` nodes. It also has
// a children specification that returns `MyDomain.MyChildElement` children for `MyDomain.MyParentElement`
// parent nodes using `ChildrenQuery` property value of the parent element.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "MyDomain", classNames: ["MyParentElement"], arePolymorphic: true },
groupByClass: false,
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.IsOfClass("MyParentElement", "MyDomain")`,
specifications: [
{
specType: "CustomQueryInstanceNodes",
queries: [
{
specType: "ECPropertyValue",
class: { schemaName: "MyDomain", className: "MyChildElement" },
parentPropertyName: "ChildrenQuery",
},
],
},
],
},
],
};
Attribute: hideNodesInHierarchy
When true
, instances nodes produced by this specification are omitted and their children appear one hierarchy level higher. Note: only instance nodes are hidden - grouping nodes are not affected by this attribute.
Type | boolean |
Is Required | No |
Default Value | false |
// The ruleset contains a root node specification for `bis.PhysicalModel` nodes which are grouped by class and hidden. This
// means class grouping nodes are displayed, but instance nodes are hidden and instead their children are displayed. The
// children are determined by another rule.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["PhysicalModel"], arePolymorphic: true },
hideNodesInHierarchy: true,
},
],
},
{
ruleType: "ChildNodes",
specifications: [
{
specType: "CustomNode",
type: "child",
label: "Child",
},
],
},
],
};
hideNodesInHierarchy: false |
hideNodesInHierarchy: true |
---|---|
Attribute: hideIfNoChildren
Specifies whether nodes created through this specification should be hidden if they have no child nodes.
Type | boolean |
Is Required | No |
Default Value | false |
// The ruleset contains root node specifications for two custom nodes which are only
// displayed if they have children. One of them has children and the other - not, so
// only one of them is displayed
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "CustomNode",
type: "2d",
label: "2d Elements",
hideIfNoChildren: true,
},
{
specType: "CustomNode",
type: "3d",
label: "3d Elements",
hideIfNoChildren: true,
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.Type = "2d"`,
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["GeometricElement2d"], arePolymorphic: true },
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.Type = "3d"`,
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["GeometricElement3d"], arePolymorphic: true },
},
],
},
],
};
hideIfNoChildren: false |
hideIfNoChildren: true |
---|---|
Attribute: hideExpression
When specified ECExpression evaluates to true
, nodes produced by this specification are omitted and their children appear one hierarchy level higher.
Type | ECExpression |
Is Required | No |
Default Value | "" |
// The ruleset contains root node specifications for two custom nodes which are only
// displayed if they have children. One of them has children and the other - not, so
// only one of them is displayed
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "CustomNode",
type: "2d",
label: "2d Elements",
hideExpression: `ThisNode.HasChildren = FALSE`,
},
{
specType: "CustomNode",
type: "3d",
label: "3d Elements",
hideExpression: `ThisNode.HasChildren = FALSE`,
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.Type = "2d"`,
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["GeometricElement2d"], arePolymorphic: true },
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.Type = "3d"`,
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["GeometricElement3d"], arePolymorphic: true },
},
],
},
],
};
hideExpression evaluates to false |
hideExpression evaluates to true |
---|---|
Attribute: suppressSimilarAncestorsCheck
Specifies whether similar ancestor nodes' checking should be suppressed when creating nodes based on this specification. See more in Infinite Hierarchies Prevention page.
Type | boolean |
Is Required | No |
Default Value | false |
// The ruleset contains a root node specification that returns the root `bis.Subject` node. Also, there are two
// child node rules:
// - For any `bis.Model` node, return its contained `bis.Element` nodes.
// - For any `bis.Element` node, return its children `bis.Model` nodes.
// Children of the root `bis.Subject` are all in the single `bis.RepositoryModel` and some of their children are in the same
// `bis.RepositoryModel` as their parent. This means the `bis.RepositoryModel` node has to be repeated in the hierarchy, but
// that wouldn't happen due to duplicate nodes prevention, unless the `suppressSimilarAncestorsCheck` flag is set.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["Subject"] },
instanceFilter: `this.ECInstanceId = 1`,
groupByClass: false,
groupByLabel: false,
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.IsOfClass("Model", "BisCore")`,
specifications: [
{
specType: "RelatedInstanceNodes",
relationshipPaths: [
{
relationship: { schemaName: "BisCore", className: "ModelContainsElements" },
direction: "Forward",
},
],
groupByClass: false,
groupByLabel: false,
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.IsOfClass("Element", "BisCore")`,
specifications: [
{
specType: "RelatedInstanceNodes",
relationshipPaths: [
[
{
relationship: { schemaName: "BisCore", className: "ElementOwnsChildElements" },
direction: "Forward",
},
{
relationship: { schemaName: "BisCore", className: "ModelContainsElements" },
direction: "Backward",
},
],
],
suppressSimilarAncestorsCheck: true,
groupByClass: false,
groupByLabel: false,
},
],
},
],
};
Attribute: priority
Controls the order in which specifications are handled — specification with higher priority value is handled first. If priorities are equal, the specifications are handled in the order they appear in the ruleset.
Type | number |
Is Required | No |
Default Value | 1000 |
// This ruleset produces a list of `bis.PhysicalModel` and `bis.SpatialCategory` instances and groups them by
// class. "Spatial Category" group will appear first because it has been given a higher priority value.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
priority: 1,
classes: { schemaName: "BisCore", classNames: ["PhysicalModel"], arePolymorphic: true },
},
{
specType: "InstanceNodesOfSpecificClasses",
priority: 2,
classes: { schemaName: "BisCore", classNames: ["SpatialCategory"], arePolymorphic: true },
},
],
},
],
};
Attribute: doNotSort
By default, nodes are sorted by their display label. This attribute allows suppressing sorting of nodes returned by this specification,
which can substantially improve performance when large numbers of nodes are involved. With this attribute set to true
, the order of
returned nodes is undefined.
Type | boolean |
Is Required | No |
Default Value | false |
// The ruleset has a specification that returns unsorted `bis.Model` nodes - the order is undefined.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: [{ schemaName: "BisCore", classNames: ["Model"], arePolymorphic: true }],
doNotSort: true,
},
],
},
],
};
Attribute: groupByClass
Controls whether returned instances should be grouped by ECClass.
Type | boolean |
Is Required | No |
Default Value | true |
// The ruleset contains a specification that returns `bis.Model` nodes without grouping them
// by class.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: [{ schemaName: "BisCore", classNames: ["Model"], arePolymorphic: true }],
groupByClass: false,
},
],
},
],
};
groupByClass: false |
groupByClass: true |
---|---|
Attribute: groupByLabel
Controls whether returned instances should be grouped by label.
Label grouping node is created only if all of these conditions match:
- There are at least two nodes with the same label.
- There's at least one sibling node with a different label.
Type | boolean |
Is Required | No |
Default Value | true |
// The ruleset contains a specification that returns `meta.ECPropertyDef` nodes without grouping them
// by label.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: [{ schemaName: "ECDbMeta", classNames: ["ECPropertyDef"] }],
groupByLabel: false,
},
],
},
],
};
groupByLabel: false |
groupByLabel: true |
---|---|
Attribute: hasChildren
Generally, when a node is created, the rules engine has to determine whether it has children before returning it. This requires evaluating child node rules and, usually, executing additional queries. This attribute allows telling the engine that nodes created by this specification always or never have children, which may substantially improve performance of creating nodes in cases when getting child nodes is expensive.
In case when the attribute value "lies":
When set to
Always
, the returned nodes always havehasChildren
flag set totrue
. Requesting children for such nodes returns empty list. It's up to the UI component to handle the case of parent node saying it has children but data source not returning any.When set to
Never
, the returned nodes always havehasChildren
set tofalse
. Requesting children for such nodes returns empty list even if there are child node rules that define children for it.
Type | "Always" | "Never" | "Unknown" |
Is Required | No |
Default Value | "Unknown" |
// This ruleset produces a hierarchy of a single root node that hosts a list of `Model` instances. Assuming all
// iModels contain at least one model, the result of this ruleset can be computed quicker by setting
// `hasChildren` attribute to `"Always"`.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "CustomNode",
type: "T_ROOT_NODE",
label: "My Root Node",
hasChildren: "Always",
},
],
},
{
ruleType: "ChildNodes",
condition: `ParentNode.Type="T_ROOT_NODE"`,
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: [{ schemaName: "BisCore", classNames: ["Model"], arePolymorphic: true }],
},
],
},
],
};
hasChildren: "Always" |
hasChildren: "Never" |
---|---|
Attribute: relatedInstances
Specifications of related instances that can be used when creating the nodes. There are several use cases when this is useful:
When there's a need to only load instances that have a related instance. Providing a related instance specification with isRequired set to
true
filters-out the instances that don't have the related instance.When there's a need to filter instances by a related instance value. The alias attribute may then be used in the
instanceFilter
attribute to reference related instance property values.When there's a need to group by related instance property values. Related instance classes are included when looking for grouping rules, which allows using related instance values for property grouping.
When there's a need to customize nodes based on related instance property values. Related instance classes are included when looking for customization rules, which allows referencing related instances and their properties in customization rule ECExpressions by their alias.
Type | RelatedInstanceSpecification[] |
Is Required | No |
Default Value | [] |
// The ruleset contains a root nodes' specification that returns nodes for `bis.Elements` that are in
// a category containing "a" in either `UserLabel` or `CodeValue` property.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: [{ schemaName: "BisCore", classNames: ["GeometricElement3d"], arePolymorphic: true }],
relatedInstances: [
{
relationshipPath: [
{
relationship: { schemaName: "BisCore", className: "GeometricElement3dIsInCategory" },
direction: "Forward",
},
],
alias: "category",
isRequired: true,
},
],
instanceFilter: `category.UserLabel ~ "%a%" OR category.CodeValue ~ "%a%"`,
},
],
},
],
};
Attribute: nestedRules
Specifications of nested child node rules that allow creating child nodes without the need of supplying a condition to match the parent node.
This is useful when the same instance node at different hierarchy levels needs to have different child nodes. Specifying a child node rule at the root level with condition to match the instance ECClass makes the rule create children for all nodes of that ECClass. When that's not desired, different child node rules may be specified as nested rules for specifications that return instance nodes of the same ECClass - that makes them have different children.
Type | ChildNodeRule[] |
Is Required | No |
Default Value | [] |
// The ruleset contains two root nodes' specifications:
// - The first one returns `bis.SpatialCategory` nodes
// - The second one returns `bis.PhysicalModel` nodes and also has a nested child node rule
// that creates a static "child" node.
// Nested rules apply only to nodes created by the same specification, so the static "child"
// node is created only for the `bis.PhysicalModel`, but not `bis.SpatialCategory`.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: [{ schemaName: "BisCore", classNames: ["SpatialCategory"] }],
groupByClass: false,
},
{
specType: "InstanceNodesOfSpecificClasses",
classes: [{ schemaName: "BisCore", classNames: ["PhysicalModel"] }],
groupByClass: false,
nestedRules: [
{
ruleType: "ChildNodes",
specifications: [
{
specType: "CustomNode",
type: "T_CHILD",
label: "child",
},
],
},
],
},
],
},
],
};
Last Updated: 15 May, 2024