The Om.Next Default Database Format, Part 1: Introduction

Using the power of React, & ClojureScript, and borrowing ideas from Falcor & Relay, Om.Next builds on the shoulders of giants to help you write more maintainable UI code.

When you start using Om.Next you might think that it is very opinionated about how you should structure your application state, but what looks like a set of baked-in rules is really just the default database structure of Om.Next.

I make sure to write about this structure as Om.Next's default database structure. Om.Next provides many hooks for you to change the way data in your application is stored/organized. Some developers use datascript as the backing data store for Om.Next applications.

That said, the default database format is quite powerful, and is suitable for many applications.

If you want to use the default database format (which is probably what you want to do if you're new to Om.Next), it can take a little while to understand how it works, and how Om.Next decides to re-render your application.

Here is an example of an atom with a map in the default database format:

(def app-state (atom {
  :statements/by-id {
    1 {:id 1 :account-number 6587}
    2 {:id 2 :account-number 5648}
    3 {:id 3 :account-number 8976}
  }
}))

None of the keyword names have any special meaning in the default database format. Your keys don't have to end with by-id or begin with current etc.

Indexes

The overall structure of the map in the previous example is:

{:type {id {<record>}
        ...}
 ...}

You can think of the top-level map as the collection of indexes in a database.

However, unlike an index in a traditional database, indexes in Om.Next may1 contain actual record data, instead of just a pointer to a record. In this way, indexes in Om.Next can be thought of as being a combination of indexes & tables from the relational database world.

Because the top-level of the state map is a bunch of indexes, the convention in Om.Next is to use namespaced keywords in the form: :<type>/by-<key> as the keys.

Conclusion

You might be wondering what the default database format gets you in Om.Next. By sticking to the default database format you can leverage Om.Next's built-in database functions to do the heavy lifting of performing queries. om/db->tree (and possibly om/tree->db) will be your best friend.

This is all just an introduction to the default database format to lay the groundwork for the most powerful feature of the database format: idents. Idents let you connect records together in a graph, and will be covered in the next installment of this series.

  1. Of course, if an index needed to directly contain the data it indexed, you would have a lot of waste if you wanted to have more than one index for a dataset. Stay tuned for the next part of this series to learn about how to build multiple indexes over the same dataset.