ScottR
ScottR

Reputation: 35

Simple reverse navigation in datomic

Learning Datomic, and having trouble with a basic case. Given a simple schema containing:

:club/name
:club/members (ref, cardinality many)

and

:people/name

So it might be populated (basically) like this:

[
{:club/name "Carpentry" :club/members [:person/name "liliana" :person/name "alexei"}]}
{:club/name "Taxidermy" :club/members [:person/name "karenna" :person/name "alexei"}]}
etc.
]

I want to do a reverse navigation to find "all the clubs 'alexei' is in". If I do this, I get only one club:

d/q '[:find (pull ?g [ {:club/_members [:club/name]}]) 
       :in $ 
       :where 
       [?g :person/name "alexei"]
       ]
     (d/db conn))

I would expect to get two hits for this example data. Am I modeling it backwards? Do I have to create a separate entity to express person-in-club?

Thanks much!

Upvotes: 2

Views: 298

Answers (1)

arcanine
arcanine

Reputation: 1953

I'm learning Datomic too, currently, I'm using Datahike because the syntax is similar & easier to dev on imo

Anyway I tried your example and came up with this:

(ns club
  (:require [datahike.api :as d]))

(def schema
  [{:db/ident :person/name
    :db/valueType :db.type/string
    :db/cardinality :db.cardinality/one}
   {:db/ident :club/name
    :db/valueType :db.type/string
    :db/cardinality :db.cardinality/one}
   {:db/ident :club/members
    :db/valueType :db.type/ref
    :db/cardinality :db.cardinality/many}])

(def database "datahike:mem://example")

(def data
  [{:club/name "Carpentry" :club/members [{:person/name "liliana"} {:person/name "alexei"}]}
   {:club/name "Taxidermy" :club/members [{:person/name "karenna"} {:person/name "alexei"}]}])

(comment
  (d/create-database database)

  (def conn (d/connect database))

  (d/transact conn schema)

  (d/transact conn data)

  (d/q '[:find (pull ?e [{:club/_members [:club/name]}])
         :where [?e :person/name "alexei"]]
       @conn))

Result:

([#:club{:_members [#:club{:name "Carpentry"}]}] [#:club{:_members [#:club{:name "Taxidermy"}]}])

Which I think is what you were looking for

There are two things that stand out to me in your comment that might have caused issue:

  • Your schema says people/name but your data says person/name
  • The club members vector in your data looks like it's mixing [ { I think you need a vector of two maps in there

But those issues might not be in your source code, could debug further if you'd like to share your source code

Hope this helps

Upvotes: 3

Related Questions