I have a data modeling question.
let's say I have a bunch of entities, pet
s and owner
s. a pet
has an owner
, and owners
have pets. I have some pathom resolvers:
(pc/defresolver pet-resolver
[{:keys [db]} {:keys [:pet/id]}]
{::pc/input #{:pet/id}
::pc/output [{:pet [:pet/id :pet/name :pet/age ,,,]}]
(entity db [:pet/id id]))
(pc/defresolver owner-resolver
[{:keys [db]} {:keys [:owner/id]}]
{::pc/input #{:owner/id}
::pc/output [{:owner [:owner/id :owner/name :owner/age ,,,]}]
(entity d/b [:owner/id id]))
now, my idea was that: wouldn't it be easy if each pet
just had an :owner/id
on their entity in our system of record? this would allow to easily nest the :owner
resolver within a query for a pet:
(parse [{[:pet/id 123] [:pet/id :pet/name {:owner [:owner/id :owner/name]}]}])
;; => {[:pet/id 123] {:pet/id 123 :pet/name "Spot" :owner {:owner/id 9 :owner/name "lilactown"}}}
however, this introduces a problem in my system of record: if I'm using something like datomic/datascript, suddenly I have entities that have a key :owner/id
, which are not in fact owners. :owner/id
no longer specifies a unique identity of an entity
that property is fine, as long as the children entities only link to one owner
maybe :pet/owner-id
and have an alias resolver to :owner/id
?
this could lead me to changing this in a couple of different ways. I could have a :pet/owner-id
key and a special pet-owner-resolver
which takes that key and looks up the owner.
(pc/defresolver pet-owner-resolver
[{:keys [db] {:keys [:pet/owner-id]}]
{::pc/input #{:pet/owner-id}
::pc/output [,,,]}
(entity db [:owner/id owner-id]))
However this is a lot of repetitive code, and my system actually has many different kinds of entities all of which can potentially have M:N relationships with each other.
another option is to nest the reference: I could have a :pet/owner
key which contains a map {:owner/id 9}
in my system of record. this way, the key isn't on an entity but rather it will be interpreted as a ref by datomic/datascript. This changes the query a bit:
(parse [{[:pet/id 123] [:pet/id :pet/name {:pet/owner [{:owner [:owner/id :owner/name]}]}]}])
;; => {[:pet/id 123] {:pet/id 123 :pet/name "Spot" :pet/owner {:owner {:owner/id 9 :owner/name "lilactown}}}}
This additional nesting... annoying? Tedious? It feels like wasted complexity> maybe `:pet/owner-id` and have an alias resolver to `:owner/id` ? that probably is the answer. I guess there are utilities for creating these that remove the boilerplate?
yes, it’s easy 🙂 you can create an a single direction alias or a bidirectional alias https://blog.wsscode.com/pathom/v2/pathom/2.2.0/connect/resolvers.html