Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespace aggregates #20

Merged
merged 14 commits into from
Nov 6, 2024
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,41 @@ To run the examples:
4. The dashboard should open and you can run functions like
`leaderboard:addScore` and `leaderboard:userAverageScore`.

### Namespaces

If you have a lot of separate data sets, you can put an identifier for the data
set at the beginning of your `sortKey`. However, if you never need to aggregate
across the data sets, there's another option which allows greater throughput
by reducing write contention: use `namespaces`.
ldanilek marked this conversation as resolved.
Show resolved Hide resolved

For example, suppose you have a bunch of leaderboard scores for several games,
and the scores for each game are independent. Then you can use the game id as a
ldanilek marked this conversation as resolved.
Show resolved Hide resolved
namespace. Then each game gets its own data structure in the aggregate
component.
ldanilek marked this conversation as resolved.
Show resolved Hide resolved

```ts
const aggregateByGame = new NamespacedTableAggregate<
[string, number],
DataModel,
"leaderboard",
Id<"games">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use an object type param here if it can also work. Knowing what each parameter means is hard. What do you think of something like:

NamespacedTableAggregate<{ 
  sortKey: [string, number],
  DataModel: DataModel, // maybe just `DataModel,` works?
  tableName: "leaderboard",
  namespace: Id<"games">
}>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also tried for a bit but couldn't get working: having this type inferred from the parameters somehow. e.g. the namespace and sortKey types should be inferable somehow, since their return values below dictate the types. But I couldn't get it working when I tried

>(components.aggregateByGame, {
sortKey: (doc) => [doc.username, doc.score],
namespace: (doc) => doc.gameId,
});
```

Now when you need to aggregate within a game, you call `.get` to narrow down the
computation to a single game.

```ts
const countTimesGamePlayed = await aggregateByGame.get(gameId).count();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Now when you need to aggregate within a game, you call `.get` to narrow down the
computation to a single game.
```ts
const countTimesGamePlayed = await aggregateByGame.get(gameId).count();
Now when you need to aggregate within a game, you call `.for` to narrow down the
computation to a single game.
```ts
const countTimesGamePlayed = await aggregateByGame.for(gameId).count();

```

There are namespaced classes for each kind of Aggregate you may want to build:
`NamespacedTableAggregate`, `NamespacedRandomize`, and
`NamespacedDirectAggregate`.

### Total Count and Randomization

If you don't need the ordering, partitioning, or summing behavior of
Expand Down
Loading