the purpose of this prototype is not to prove the usefulness of a query DSL with ECS per se. instead, the purpose is to demonstrate the advantages of thinking of the game state as a database.
graphecs uses a modified subset of neo4j's [cypher](https://neo4j.com/docs/cypher-manual/current/introduction/) query language. neo4j is a graph database with a focus on relationships between data. it has many similar features to SQL-like languages but the ergonomics of relating data is significantly better.
### Querying entities
```cypher
MATCH (e)
RETURN e
```
this is a basic query to return every entity in current ecs world. `MATCH` clauses begin any expression that queries for data. `RETURN` defines what data will be returned by the query. an example of the output may look like this
```js
[
{ e: 0 },
{ e: 1 },
{ e: 2 },
]
```
```cypher
MATCH (e:Entity, :Player)
RETURN e
```
this query specifies two components to match for a single node. here, it explicitly identifies the `:Entity` component but this is optional -- binding a variable without any component label will be bound to the entity's id. additionally, it requires the node to also have the `Player` component. it doesn't bind that component to any variable, however. matching against multiple components in a single node acts like an AND operator -- in this case, `Entity AND Player`.
```cypher
MATCH (:Player)-[:Knows]->(n:NPC)
RETURN n
```
this query matches against a relationship: any `Player` which `Knows` an `NPC`. it will return a list of all NPCs which have this relationship with the player. in the prototype, edges are just entities with `from` and `to` properties
in this example, we have an `Item` component with a single property: `damage`. it can be useful to only return a single property from a component. the result of this query may look like the following
```js
[
{ item: { damage: 10 } },
{ item: { damage: 15 } },
{ item: { damage: 20 } },
]
```
accessing nested data like this can get a bit unwieldy, but its possible to alias variables
```cypher
MATCH (item:Item)
RETURN item.damage AS damage
```
```js
[
{ damage: 10 },
{ damage: 15 },
{ damage: 20 },
]
```
### Filtering queries
```cypher
MATCH (h:Health)
WHERE h.current <10
RETURN h
```
it is also possible to filter results via the `WHERE` clause. the following operators are supported in graphecs: `> >= < <= = AND OR XOR ( )`
```cypher
MATCH (n)-[d:Damaged]->(e, h:Health)
WHERE d.damage > h.current AND h.current > 0
RETURN e
```
this would return every entity id that has a relationship that deals more damage than its remaining health and isn't already dead
it is also possible to match against specific component properties. in this query, it will match any entity which has a `Health` component where its `current` is equal to 35