xtdb

jf 2024-09-05T06:18:45.821209Z

question about database design: I suspect this probably does not matter as much for XTDB, but in my app, I have different types of users. There are some common attributes between them (basically first/last name, email, and maybe contact number)... and then some other fields that are unique to each type of user. Would the fact that I am using XTDB favour using single table inheritance, concrete table inheritance (separate table - or I guess document - for each type of user)... or does it not matter?

tatut 2024-09-06T08:19:00.064509Z

you can still get a doc by id, but yes the iteration of all docs of a type might be a bad usecase

tatut 2024-09-06T08:19:28.102259Z

we used these single key/value maps as ids in a project, and at least it was good when inspecting the database, you always know what you are dealing with

jf 2024-09-06T08:21:58.984149Z

it is a nice idea... what about using a prefix? so "<prefix>"-<rest of id>. Technically not a UUID, but u could have the <rest of id> portion be an actual uuid. This also of course assumes that there is a way to query using prefix when you're searching for "user type A", vs type B, etc.

jussi 2024-09-06T09:05:56.180889Z

We have used namespaced id's in XTDB v1, like

:xt/id {:user/id <uuid>}
:xt/id {:customer/id <uuid>}

tatut 2024-09-05T07:10:13.723139Z

v2? You can just insert all different types of users in the same users table, it doesn’t matter if they have different attributes

jf 2024-09-05T07:15:01.316119Z

Sorry no, v1

tatut 2024-09-05T07:19:16.028099Z

in v1 there are no tables, so I don’t know how you can have “table inheritance”?

tatut 2024-09-05T07:19:25.291679Z

just documents

tatut 2024-09-05T07:19:38.755459Z

but the same applies, there is no requirement for all documents to have the same attributes

✅ 1
jf 2024-09-05T08:50:49.705159Z

Gotcha. Thank you

jf 2024-09-05T09:02:39.025109Z

This link should help explain STI: https://docs.gitlab.com/ee/development/database/single_table_inheritance.html

tatut 2024-09-05T09:33:22.859489Z

personally, I would mostly avoid ORMs and use a language with 1st class data

tatut 2024-09-05T09:33:59.920709Z

but the discussion of having some kind of “type” attribute for discrimnating between different types of docs is valid

jf 2024-09-05T09:34:07.524709Z

yes. The question is not about ORMs, but about how folks would structure their documents

tatut 2024-09-05T09:34:36.390739Z

best is to not need an attribute just to specify a document’s “type”

tatut 2024-09-05T09:35:18.789879Z

you can do that by querying by some attribute that only occurs in that type, or you could even encode the type in the doc id in v1 (like {:sometype <uuid>} map as the xt id

jf 2024-09-05T09:36:21.812639Z

hmm. I’ve not considered that, but that’s an interesting idea. Right now my ids are UUIDs.

jf 2024-09-05T09:37:41.560029Z

I’ve been wondering about the utility of using UUIDs, and having to do a parse-uuid (give the string representation) step just to do a query

jf 2024-09-05T09:38:26.622369Z

sorry, maybe I misunderstood. Are you saying to use a map as the xt id?

tatut 2024-09-05T09:38:28.173539Z

iirc, you can even query all docs of a “type” by doing range {:sometype <0000-…>} - {:sometype <ffff-...>}` query

tatut 2024-09-05T09:38:41.958199Z

yes, use the whole map as the id

jf 2024-09-05T09:42:04.135719Z

on the topic of identifiers, have you looked at something like snowflake ids (not necessarily the implementation as done by twitter; more info https://en.m.wikipedia.org/wiki/Snowflake_ID) as opposed to UUIDs?

tatut 2024-09-05T09:43:22.678429Z

haven’t, but UUIDv7 looks nice as well

jf 2024-09-05T10:18:42.536739Z

thank you for that note! re that range query, would you be able to give me an example of how to do that query?

tatut 2024-09-05T10:25:30.511319Z

sorry, I don’t have an example handy, but just using the <= and >= in datalog will give you range queries

jf 2024-09-05T10:27:21.146159Z

no worries. I’m aware of the predicate functions; just not sure about how to query when the value in question is “nested”, instead of a “direct” EAV value

refset 2024-09-05T14:59:29.042939Z

hey @jf.slack-clojurians be aware predicates over nested data won't benefit from indexing, you will essentially end up with table scans - but you can do it like: [?e :att ?some-map] [(get ?some-map :some-key) ?val] [(<= ?val 100)] you can similarly use get-in, it's just calling clojure.core/* fns

jf 2024-09-05T15:02:05.532649Z

thank you for that note. In that case, I think i'll refrain from using maps

👌 1