# Dragginz ORM Indexes

**URL:** <https://forum.dfinity.org/t/dragginz-orm-indexes/22184>\
**Category:** Developers\
**Created:** [August 16, 2023, 9:19am UTC](https://forum.dfinity.org/t/dragginz-orm-indexes/22184 "2023-08-16T09:19:53Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![anon98822045](https://avatars.discourse-cdn.com/v4/letter/a/ce73a5/32.png) [@anon98822045](https://forum.dfinity.org/u/anon98822045)\
**Post date:** [August 16, 2023, 9:19am UTC](https://forum.dfinity.org/t/dragginz-orm-indexes/22184/1 "2023-08-16T09:19:53Z")

</div>

Hi all, wanted to share v1 of our indexing system. It’s written in Rust and uses the ic-stable-structures crate. This is going to be part of the Dragginz ORM that we’ll open source at some point (probably about 6 months away i think.) Feel free to criticise, I probably don’t know what I’m doing.

**Step 1 : Define the Entity, I’ll show a complicated one…**

![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/3/3387f6adb30cdf1f83420a609e82cab2ac1f78fa.png)

You can have multiple indexes, they can be on any combination of fields (but not those named as primary/sort keys). There’s one optional argument for now, unique.

The API uses a CompoundKey which is a Vec, for example [“character\_id”, “pet\_id”]. The database itself uses a SortKey however, so `Character=123/Pet=456` so we can do range queries and pull parent and child data in the same call. Thanks @icme

**Step 2 : CTOR all the things**

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/2/25a8b52f5e1e841b5a224e0bdd6e48972db94fe1.png)

Every entity/newtype/set/map/list/whatever in our ORM gets sent via ctor to a schema. This structure is serialized to a file so that the front-end can use it, but wait …

**Step 3 : Schema goes into memory via crude hack**

![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/d/d97094829269e60ac3ef121e39849429cb10d56c.png)

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/d/d8edc6c983dafc4cfce113db71c2ca33c7f146e3.png)

This is the awesome bit. Json goes into file via a build script, and we can read it using the include\_str! macro and Arc allows us to share a pointer around the ORM.

**Step 4 : CRUD**

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/a/a28392799b51f7e8a4e5c4dbb4fdc62f8cf8d101.png)  
 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/d/d847080051f7288d96041dd84786e19f52b48766.png)

The pre-build Schema puts in an automatic crud endpoint for every entity within a canister. We did think about using a variant that represents every entity but the code got really messy.

**Step 5 : The Store**

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/8/87587602eead7398674e4bddd312e23115461476.png)

The Store requires two stable memories and has a reference to the Schema which knows what entities have which indexes.

As we may be sending types to the front-end we need to generate candid for them, so all the types (even ones used internally via the ORM are defined in the Schema).

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/4/4d7fa7cbf47939014b6d1f8acee0e58a5cbc0209.png)

**Step 6 : The Candid**

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/4/4806d6b92cc7fe837d2f48139ef235ea7fd5076d.png)

All automatically generated by the schema!

**Step 7 : The Query**

We use a WhereQuery structure that allows us to do pagination, ranges, and most importantly indexes.

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/9/92d9f2c54fe761db48e2160cdc36ed503028e463.png)

Why do we need this? One of the use-cases is a loot table where you have to keep pulling rows using different criteria.

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/f/f368975d9c3a16606d97605bb178e015156ec72e.png)

Indexes can get out of date if the schema changes, so the system is designeed to allow dropping and rebuilding of index data.

**Step 8 : Testing**

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/d/db36b8c33a3d453d27a085975efbf9c27f8ae56c.png)

Here you can see the API in action. We have to run the tests via an endpoint because stable-structures exists within Wasm.

I will be in Zurich in September to show people what we’ve been working on. Feedback appreciated, I’m cool if I have to write the whole thing from scratch, just want it to be as good as it can be.

---

<div class="post-metadata">

**Author:** ![anon98822045](https://avatars.discourse-cdn.com/v4/letter/a/ce73a5/32.png) [@anon98822045](https://forum.dfinity.org/u/anon98822045)\
**Post date:** [August 16, 2023, 9:29am UTC](https://forum.dfinity.org/t/dragginz-orm-indexes/22184/2 "2023-08-16T09:29:08Z")

</div>

More information on the ORM… here are the “shapes / types” we support :

![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/4/4a57e46e340a754a2f34586ff770ad59abf04b03.png)

Map is a HashMap, Set a HashSet and List is a Vec. This allows us to do cool stuff like ItemAttributes, where each Item can have a maximum of one Attribute per type.

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/2X/c/c7b746a26c59a3771c7dda4bd329dbbbb1606b3c.png)

Perfect for extremely complicated game design!

All Enums automatically derive a trait where you can do

```auto
fn variant_name() -> String

```

and that’s used as the Hash bound for the HashSet
