Skip to content

Commit 2e24ccc

Browse files
committed
Update relation query explanations and examples
1 parent a026e6f commit 2e24ccc

2 files changed

Lines changed: 39 additions & 20 deletions

File tree

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"libtcod",
2121
"liskin",
2222
"maxdepth",
23+
"Mertens",
2324
"modindex",
2425
"Mypy",
2526
"Numpad",

README.md

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,45 @@ True
207207

208208
## Relations
209209

210-
Use `Entity.relation_components[component_key][target] = component` to associate a target entity with a component.
211-
Use `Entity.relation_tag[tag] = target` to associate a tag exclusively with a target entity.
212-
Use `Entity.relation_tags_many[tag].add(target)` to associate a tag with multiple targets.
210+
Entity relations are unidirectional from an origin entity to possibly multiple target entities.
211+
212+
- Use `origin.relation_tag[tag] = target` to associate an origins tag exclusively with the target entity.
213+
This uses standard assignment and is useful for tags which would not make sense with multiple targets.
214+
Reading `origin.relation_tag[tag]` returns a single target while enforcing the invariant of only having one target.
215+
- Use `origin.relation_tags_many[tag].add(target)` to associate a tag with multiple targets.
216+
This supports `set`-like syntax such as adding or removing multiple targets at once.
217+
This allows for many-to-many relations.
218+
- Use `origin.relation_components[component_key][target] = component` to associate a target entity with a component.
219+
This allows storing data along with a relation.
220+
This supports `dict`-like syntax.
221+
The `component_key` can be queried like a normal tag.
213222

214-
Relation queries are a little more complex than other queries.
215-
Relation tags and relation components share the same space then queried, so 'normal' tags should not be in the format of a component key.
216-
Relations are unidirectional, but you can query either end of a relation.
223+
### Relation queries
224+
225+
Relations are queried with `registry.Q.all_of(relations=[...])`.
226+
This expects 2-item or 3-item tuples following these rules:
227+
228+
- Use `(tag, target)` to match the origin entities with the relation `tag` to `target`.
229+
- If `tag` is a component key then component relations are also matched.
230+
This means you should be careful with tags which look like component keys.
231+
- `target` can be a specific entity. This means only entities relating to that specific entity will be matched.
232+
- `target` can be query itself. This means only entities relating to a match from the sub-query are matched.
233+
- `target` can be `...` which means an entity with a relation to any entity is matched.
234+
- To reverse the direction use a 3-item tuple `(origin, tag, None)`. `origin` can be anything a `target` could be.
235+
236+
Relations using sub-queries may be chained together.
237+
See [Sander Mertens - Why it is time to start thinking of games as databases](https://ajmmertens.medium.com/why-it-is-time-to-start-thinking-of-games-as-databases-e7971da33ac3) to understand the repercussion of this.
238+
239+
You can use the following table to help with constructing relation queries:
240+
241+
| Matches | Syntax |
242+
| ------------------------------------------------------------------- | :--------------------------------------: |
243+
| Origins with a relation `tag` to `target_entity` | `(tag, target_entity)` |
244+
| Origins with a relation `tag` to any target entity | `(tag, ...)` (Literal dot-dot-dot) |
245+
| Origins with a relation `tag` to any targets matching a sub-query | `(tag, registry.Q.all_of(...))` |
246+
| Targets of the relation `tag` from `origin_entity` | `(origin_entity, tag, None)` |
247+
| Targets of the relation `tag` from any origin entity | `(..., tag, None)` (Literal dot-dot-dot) |
248+
| Targets of the relation `tag` from any origins matching a sub-query | `(registry.Q.all_of(...), tag, None)` |
217249

218250
```py
219251
>>> @attrs.define
@@ -243,17 +275,3 @@ True
243275
True
244276

245277
```
246-
247-
### Relation queries
248-
249-
You can use the following table to help with constructing relation queries.
250-
`tag` is a component key if you are querying for a component relation.
251-
252-
| Includes | Syntax |
253-
| ------------------------------------------------------------------- | :--------------------------------------: |
254-
| Entities with a relation tag to the given target | `(tag, target_entity)` |
255-
| Entities with a relation tag to any target | `(tag, ...)` (Literal dot-dot-dot) |
256-
| Entities with a relation tag to the targets in the given query | `(tag, registry.Q.all_of(...))` |
257-
| The target entities of a relation of a given entity | `(origin_entity, tag, None)` |
258-
| The target entities of any entity with the given relation tag | `(..., tag, None)` (Literal dot-dot-dot) |
259-
| The target entities of the queried entities with the given relation | `(tag, registry.Q.all_of(...))` |

0 commit comments

Comments
 (0)