An entity is defined by the components associated with it. Components grant the data (component values) to entities that are needed to model a specific behavior. This leaves systems with the implementation of that behavior.

In order for a system to implement entity behavior, it must first find all entities of interest. This is done using queries.

A system may query entities using it’s world’s of method.

let Planet = j.type(PlanetGeometry, PlanetType, ...)

let orbitPlanetsSystem = (world: j.World) => {
  let planets = world.query(Planet)

Entities that match the query’s terms are iterated using the query’s each method.

planets.each(planet => {
  // `planet` has all components defined in the `Planet` type

Query terms may include types, components (including relation tags and relationship components, slot tags and slot components), and filters, discussed later in the chapter.

Query Views

Systems are often highly specific about the entities they resolve while only utilizing a small subset of the entities’ component values. The component values a query iteratee recieves can be narrowed using the query’s as method.

  .query(Hippo, Element(Lightning), StandingIn(Water), Health)
  .each((hippo, hippoHealth) => {
    // (do something with just the hippo's health)

Query Filters

The results of a query can be further narrowed using query filters. Javelin currently has two query filters: Not and Changed.


The Not filter excludes entities that match a given component.

world.query(Planet, j.Not(Atmosphere)).each(planet => {
  // `planet` does not have an atmosphere component

Without can be used with more complex component types like relationships and slots. The following query could be expressed in plain terms as “all gas planets that are not in the Sol system”:

world.query(Planet, PlanetType(Gas), j.Not(j.ChildOf(solSystem)))

Another example: “all non-gas planets”:

world.query(Planet, j.Not(PlanetType(Gas)))


The Changed filter is under development.