Query for child components
Updated: Jun 20, 2025
The childrenOf is an advanced and experimental query which allows you to retrieve a list of entities that are considered children of a specified parent entity based on a linked entity attribute. This is particularly useful for creating parent-child relationships between entities.
The childrenOf query takes two parameters:
- The parent entity
- The ID of the linked entity attribute that defines the parent-child relationship
When the query runs, it returns all entities that have the specified attribute pointing to the parent entity.
Setting up linked entity attribute
Before you can use childrenOf queries, you need to register the entity attribute as a linked entity attribute:
// Do this in your Activity's onCreate method:
EntityContext.getDataModel()!!.registerLinkedEntityAttribute(MyComponent.parentId)
// MyComponent should have an entity attribute called "parent", and "MyComponent.parentId" is the ID of that attribute
This tells the DataModel to build and maintain a hierarchy based on this attribute, which enables efficient querying of parent-child relationships.
Here’s an example of using childrenOf queries in a “tree” hierarchy system:
@OptIn(SpatialSDKExperimentalAPI::class)
class TreeHierarchySystem : SystemBase() {
init() {
// Register the parent entity attribute as a linked entity attribute
EntityContext.getDataModel()!!.registerLinkedEntityAttribute(TreeNode.parentId)
}
override fun execute() {
// Process all root nodes (nodes without parents), assuming top-level entities also have a TreeNode component
val rootNodesQuery = Query.where { has(TreeNode.id) }
.filter { by(TreeNode.parentData).isEqualTo(Entity.nullEntity()) }
for (rootEntity in rootNodesQuery.eval()) {
processNodeAndChildren(rootEntity)
}
}
private fun processNodeAndChildren(entity: Entity) {
// Process this node
val treeNode = entity.getComponent<TreeNode>()
// Apply any node-specific logic here
// ...
println("Processing node: ${treeNode.name}")
// Find and process all children of this node
val childrenQuery = Query.where { childrenOf(entity, TreeNode.parentId) }
for (childEntity in childrenQuery.eval()) {
processNodeAndChildren(childEntity)
}
}
}
Below is TreeNode’s XML definition:
<?xml version="1.0" encoding="utf-8"?>
<ComponentSchema packageName="test.package.name">
<Component name="TreeNode" >
<EntityAttribute name="parent" />
<StringAttribute name="name" />
</Component>
</ComponentSchema>
In this example:
- The
TreeHierarchySystem manages a hierarchy of tree nodes. - In the
init method, TreeNode.parentId is registered as a linked entity attribute. Note that this is a required step for using childrenOf queries and typically happens in the Activity’s onCreate lifecycle callback. - In the
execute method, the system first finds all root nodes (nodes without parents). - For each root node, the system processes it and then recursively processes all its children.
- The system uses
childrenOf(entity, TreeNode.parentId) to query for all direct children of a node.
Consider the following example tree structure:
/**
*
* A
* / \
* B C
* / \ \
* D E F
*/
val A = Entity.create()
val B = Entity.create()
val C = Entity.create()
val D = Entity.create()
val E = Entity.create()
val F = Entity.create()
A.setComponent(TreeNode(parent = Entity.nullEntity(), name = "A"))
B.setComponent(TreeNode(parent = A, name = "B"))
C.setComponent(TreeNode(parent = A, name = "C"))
D.setComponent(TreeNode(parent = B, name = "D"))
E.setComponent(TreeNode(parent = B, name = "E"))
F.setComponent(TreeNode(parent = C, name = "F"))
When the TreeHierarchySystem executes, it will first find the root nodes (A) and then process them. It will then recursively process all their children (B, C), and so on, resulting in the following output:
Processing node: A
Processing node: B
Processing node: D
Processing node: E
Processing node: C
Processing node: F
- Register linked entity attributes in your Activity’s
onCreate method. - Use meaningful attribute names for parent-child relationships to make your code more readable.
- Consider the performance implications of deep hierarchies, as traversing large trees can be expensive.