Say that I’m working on a Google Calendar-like database where people store meetings.
- A meeting have a start time and end time (mostly an hour or two).
- A meeting can occupy multiple rooms.
- Meetings might temporarily overlap (we don’t enforce strict collision control).
Assuming that a user often need to query things like “give me all the meeting today at this specific room(s)”, what’s the recommended index strategy?
(01) R-tree
In PostgreSQL we might do
create table meetings (room int, during tstzrange);
create index meeting_index on meetings using gist (during);
But since Datomic does not have a GiST index (R-tree) so it’s not an option.
(02) Composite Tuples
Since the rooms are limited and most of the meetings took place within an hour or two, we can cheat a little by creating a date index.
[{:db/ident :meeting/rooms
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}
{:db/ident : meeting/dates
;; Datomic does not support java.time.LocalDate so we have to go with strings
:db/valueType :db.type/string
;; It's :db.cardinality/many since a meeting might take place at the midnight (yikes) and span two dates
:db/cardinality :db.cardinality/many}]
But the query might be inefficient if we have lots of meeting (more than a million) within a day. So I thought maybe we can do
[{:db/ident :meeting/date-room-index
:db/valueType :db.type/tuple
:db/tupleAttrs [:meeting/dates :meeting/rooms]
:db/cardinality :db.cardinality/many}]
Which trades storage space for query time, but Datomic does not allow :db.cardinality/many on composite tuples…
Execution error (ExceptionInfo) at datomic.client.api.async/ares (async.clj:58).
First error: :db.error/tuple-of-attrs-must-be-card-one
Ref: https://portal.feedback.eu.pendo.io/app/#/case/113782
(03) Hilbert Curves
I did find a report that implements R-Tree / Hilbert Curves on top of Datomic on-prem, but the codebase is no longer maintained.
(04) …
I have not thought of a elegant solution. Dear mighty Clojure / Datomic community, any thought?