Queries
Updated: Oct 6, 2025
In Spatial SDK applications, you may want to write different systems to apply logic to specific entities. For example, consider a scenario where you need to update physics, trigger collision callbacks, or apply game logic to all entities that have a Physics component. Instead of manually iterating over all the entities in a Spatial SDK application, Queries provide a unified interface to access the relevant entities.
Queries are an essential tool when writing systems for a Spatial SDK application. They enable dynamic retrieval of entities based on specific component criteria. You don’t have to worry about the details of how entities are retrieved.
Here is a simple example of creating a Query:
val q: Query = Query.where { has(Physics.id) }
The query system is initiated by creating a query object that filters entities based on specific criteria. For this query, the entities must have a Physics component.
Once the query is defined, it can be evaluated by invoking the eval method:
val entities: Sequence<Entity> = q.eval()
Under the hood, the query won’t run until eval is invoked.
There are two categories of operators in a query: conditional and logical operators.
These operators check for specific conditions or states.
- The
has operator checks if the entity has certain types of components. - The
changed operator checks if certain components of the entity have changed in the last tick. - The
changedSince operator checks if certain components of the entity have changed since a specific data model version. Read more in changedSince query. - The
childrenOf operator returns entities that are children of a specific entity. Read more in childrenOf query.
These operators are used to combine conditions or logical expressions.
- The
and operator is used to combine the two conditions on either side. - The
or operator is used to combine the two conditions on either side with logical OR.
You can create complex queries by mixing and matching the query operators.
val q: Query = Query.where { has(Scale.id) and changed(Scale.id, Mesh.id, Panel.id) }
Once evaluated, this query will return a list of entities that have the Scale component, and whose attributes of the Scale, Mesh, and Panel components have changed since the last tick.
You can refine your query results by applying filters.
val droneEntities =
Query.where { has(DroneComponent.id, Transform.id) }
.filter { by(DroneComponent.enabledData).isEqualTo(true) }
.eval()
In this example:
- The query first selects entities that have both DroneComponent and Transform components.
- The filter method is then used to ensure that only entities with the boolean attribute
enabled set to true are included in the results. - The eval method executes the query, returning a sequence of entities that meet all specified criteria.
For more information about query filtering, refer to
Filters.
You can sort the results of a query by using the sort method.
// Sort by rotation speed, descending, and take the first 10 results, if any
val sortedEntities =
Query.where { has(DroneComponent.id, Transform.id) }
.filter { by(DroneComponent.enabledData).isEqualTo(true) }
.sort {
with {
by(DroneComponent.rotationSpeedData).desc()
}
take(0, 10)
}
.eval()
In this example:
- The query first selects entities that have both
DroneComponent and Transform components. - The
filter method is then used to ensure that only entities with the boolean attribute enabled set to true are included in the results. - The
sort method is then used to sort the results by the rotationSpeed float attribute in descending order. - The
take method is used to limit the results to the first 10 entities. - The
eval method executes the query, returning a sequence of entities that meet all specified criteria.
For more information about query sorting, refer to
Sorting.