This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-05-31
Channels
- # announcements (6)
- # babashka (40)
- # beginners (6)
- # calva (1)
- # cider (1)
- # clerk (43)
- # clj-kondo (3)
- # clojure (93)
- # clojure-denver (8)
- # clojure-europe (52)
- # clojure-norway (20)
- # clojure-sweden (7)
- # community-development (5)
- # datascript (15)
- # datomic (30)
- # emacs (24)
- # events (15)
- # fulcro (23)
- # graalvm (12)
- # gratitude (1)
- # helix (4)
- # honeysql (4)
- # hoplon (39)
- # hyperfiddle (7)
- # introduce-yourself (1)
- # jobs (1)
- # jobs-discuss (26)
- # lambdaisland (3)
- # lsp (6)
- # matcher-combinators (2)
- # matrix (5)
- # meander (39)
- # nrepl (4)
- # nyc (1)
- # off-topic (5)
- # portal (73)
- # practicalli (1)
- # re-frame (2)
- # reitit (22)
- # releases (1)
- # remote-jobs (4)
- # shadow-cljs (5)
- # sql (17)
- # testing (1)
- # tools-deps (15)
I'm wondering whether there's an idiomatic way to do recursive reverse lookups that I'm missing. Here's the schema I'm working with:
{ :code/label {:db/cardinality :db.cardinality/one}
:code/children {:db/cardinality :db.cardinality/many
:db/valueType :db.type/ref
:db/isComponent true}
:matter/codes {:db/cardinality :db.cardinality/many
:db/isComponent true
:db/valueType :db.type/ref}
}
Every matter can point to zero or more codes, and codes can be nested to an arbitrary depth. Here, when I want to find all of the codes that are a component of a given matter, I can do a simple pull:
(ds/pull ds-db '[:matter/code] eid) => all the nested codes
. And if I want to find the immediate parent of a code entity, I can use a reverse lookup like this: (ds/pull ds-db '[:matter/_codes :code/_children] eid) => db/id of the parent.
But I don't know how to find the root node, i.e. the matter eid, given the eid of any given code. I tried (ds/pull ds-db '[{:code/_children ...}] eid)
based on what I thought might work from the datalog documentation, but that just returns nil. The only other approach I could think of was perhaps manually doing some kind of (loop ...)
solution that would contain a pull function in it. This isn't really ideal, given that I'm trying to do this in the context of re-posh
, which doesn't really make the datascript database visible to subscriptions, as far as I can tell.
Any pointers would be really appreciated!Given that (ds/pull ds-db '[:matter/_codes :code/_children] eid)
was used to find the first parent, I’d guess that (ds/pull ds-db '[{:code/_children ...}{:matter/_codes ...}] eid)
would be used to find all of your parents, but I’m not sure I understand your data structure, could you give an example?
Sure, here's the setup:
(let [schema {:code/label {:db/cardinality :db.cardinality/one}
:code/children {:db/cardinality :db.cardinality/many
:db/valueType :db.type/ref
:db/isComponent true}
:matter/codes {:db/cardinality :db.cardinality/many
:db/isComponent true
:db/valueType :db.type/ref}}
conn (ds/create-conn schema)
db (ds/db-with @conn [{:db/id -1
:matter/codes -2}
{:db/id -2
:code/label "A"
:code/children -3}
{:db/id -3
:code/label "A-1"
:code/children -4}
{:db/id -4
:code/label "A-1-1"}])
]
.......
)
(ds/pull db '[:code/_children :matter/_codes] 4) => #:code{:_children #:db{:id 3}}
(ds/pull db '[:code/_children :matter/_codes] 3) => #:code{:_children #:db{:id 2}}
(ds/pull db '[:code/_children :matter/_codes] 2) => #:code{:_children #:db{:id 1}}
(ds/pull db '[*] 1) => { :db/id 2, :code/children [ { :db/id 3, :code/children [ { :db/id 4, :code/label "A-1-1" } ], :code/label "A-1" } ], :code/label "A" }
BUT
(ds/pull db '[{:code/_children ...}] 4) => nil
(ds/pull db '[{:code/_children ...} {:matter/_codes ...}] 4) => nil
Poking around I see people referencing recursive rules, so maybe that's the way to get what I want? Could you help me see what that would look like?
In my opinion recursive rules suck because they are really slow, but yes you could write a recursive query rule to do this. I’m not really well versed in them because I don’t write them, but I learned them from here https://www.learndatalogtoday.org/chapter/8
Bingo! Thanks! For anyone who finds this thread in the future, (ds/pull '[:db/id {:code/_children ...}{:matter/_codes ...}] 4)
did the trick.
@U050UBKAA is this a bug with datascript? I would think his first example should work
I think (ds/pull db '[:db/id {:code/_children ...}] 4)
works but (ds/pull db '[{:code/_children ...}] 4)
does not
@U011FLPNDD2 can you make a minimal repro and report it to github issues if that’s the case?
Sorry, I missed these. Yes, Josh said it correctly. @U050UBKAA