Imagine your canister stores a list of objects in stable memory:
struct User {
id: [u8; 12],
name: String,
age: u8,
registeration_date: u64,
active: bool
}
Your main index is based on the id and stored in a StableBTreeMap
. Then, you realise you need to list users based on registration_date
. So, you add an index, a Log
or perhaps another map. But… doing some more wireframes you realise you need the following:
Show all active users with an age over 18 sorted by name
. And oh, you have 10K users, so it would be good to do some pagination of the query results. Searching would be nice as well.
Now, adding another index isn’t enough.
I’d be interested to hear if someone has any good ideas how to solve patterns like this? It would be easy to dismiss the whole thing, saying that the core canister of an app should not handle arbitrary queries like this. It would risk bloating core canisters. Core canisters should resemble smart contracts and not be built for the frontend performance/UX needs. But if the core canisters doesn’t handle those queries, then who?
One option would be to add “indexing/query canisters” to the project. Using some pubsub setup, those canisters would stay up to date with the core canisters and then expose graphql endpoints on the http interface or something. This sounds like a lot of work.
If we were building an ETH application, the frontend would be hosted on Vercel and queries would be made possible by creating indexes on https://thegraph.com. Next.js, running on Vercel would also cache queries, allowing for loads of traffic if needed.
Is someone building “The Graph” for IC?