very basic question to get me started. Suppose I have a database of sales by country:
[{:sales/country "CN" :sales/amount 1000 :sales/account "XYZ"} ...]
I would like to also have a list of facts about each country something like:
[{:country/short-name "CN" :country/long-name "China" ...}]
And then do queries of the type "list all sales that happened in China (using the long-name)".
Is that one database? How do I make it clear there are two distinct schemas? Do I transact the first schema then the sales data, and later the country schema and data?
EDIT: sorry my question wasn't clear. Here is live example:
(d/transact! conn
[{:country/code "BR" :country/name "Brazil"}
{:country/code "CN" :country/name "China"}])
(d/transact! conn
[{:sales/country "CN" :sales/amount 1000 :sales/account "XYZ"}
{:sales/country "CN" :sales/amount 1000 :sales/account "AAA"}
{:sales/country "BR" :sales/amount 1000 :sales/account "BBB"}}
])
I was able to run a query to join the tables and get the results I wanted. What I don't understand is what is best practice to define my schema. Is it just one schema or two of them, one for each table. Can I do this:
(def schema {:country/code {:db/valueType :db.type/string :db/unique :db.unique/identity}
:country/name {:db/valueType :db.type/string}
:sales/account {:db/valueType :db.type/string :db/unique :db.unique/identity}
:sales/country-code {:db/valueType :db.type/string}
:sales/amount {:db/valueType :db.type/integer}
})
And is there a better way to define in the schema that country/code and sales/country-code are the same "key"?
Thanks,
You can only have 1 schema, but that should be enough. Use namespace in keywords to distinguish between different “domains” (:country/*
for info about countries, :sales/*
for info about sales).
Datomic is more of a column store, so any entity can have any attribute, and you can even mix different “tables” on a single attribute (I don’t recommend it, but it’s possible).
Your use of :country/code
is what Datomic calls “an external id”. This is also a good practice, although, there’s no way to specify that :sales/country
is a reference to :country/code
.
What I suggest you do instead is make :sales/country
a Datomic reference:
:sales/country-code {:db/valueType :db.type/ref}
and then link to it in transaction using lookup ref:
@(d/transact! conn [{:sales/country [:country/code "CN"] :sales/amount 1000 :sales/account "XYZ"})
This will make sure country with this code exist during transaction time. You’ll also get benefits like easy retrieving country info from sales using entities/pull.