This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-22
Channels
- # announcements (6)
- # babashka (8)
- # beginners (136)
- # cider (5)
- # cljs-dev (1)
- # cljsrn (1)
- # clojure (198)
- # clojure-argentina (4)
- # clojure-australia (1)
- # clojure-europe (25)
- # clojure-italy (4)
- # clojure-nl (5)
- # clojure-poland (1)
- # clojure-spec (4)
- # clojure-uk (4)
- # clojuredesign-podcast (4)
- # clojurescript (36)
- # conjure (11)
- # data-science (1)
- # datomic (6)
- # defnpodcast (1)
- # deps-new (5)
- # emacs (7)
- # events (1)
- # fulcro (10)
- # graalvm (9)
- # graalvm-mobile (10)
- # helix (9)
- # introduce-yourself (1)
- # jackdaw (1)
- # jobs-discuss (5)
- # kaocha (6)
- # lsp (10)
- # malli (11)
- # missionary (28)
- # off-topic (2)
- # pathom (24)
- # pedestal (7)
- # portal (1)
- # re-frame (12)
- # reagent (2)
- # reitit (1)
- # remote-jobs (1)
- # sci (7)
- # shadow-cljs (6)
- # sql (6)
- # tools-deps (10)
- # vim (9)
- # xtdb (19)
Hi all, It seems coll types aren't preserved when querying. As a crude example say I want to put the following document into my db.
(crux/submit-tx my-node
[[:crux.tx/put {:crux.db/id 123
:x #{1 2 3}
:y [1 2 3]}]])
If I want to retrieve the values bound to my keys I get the following
(q '{:find [x]
:where [[e :x x]]})
;=> #{[3] [2] [1]}
(q '{:find [y]
:where [[e :y y]]})
;=> #{[3] [2] [1]}
I guess this relates to how crux stores facts, not documents.
Is there no simple way to just retrieve the value as it was stored?
I can preserve the type this way
(q '{:find [(pull e [:x])]
:where [[e :crux.db/id]]})
;=> #{[{:x #{1 3 2}}]}
but the nesting is pretty frustrating.Hi again 🙂
> I guess this relates to how crux stores facts,
pretty much, yep. Sets and vectors get decomposed into individual AVs.
If you can accept retrieving :x #{1 2 3}
as a vector and not a set, then you can use the built-in get-attr
predicate which will pull the individual AVs back into a relation:
i.e. [(get-attr e :x) vs] ;; vs => [1 2 3]
And if you really need the original value of :x
as seen in the source document (i.e. retrieve the set), you can use the entity API inside of the query and get
the value out, e.g.
[[(crux.api/entity $ e) ent]
[(get ent :x) vs]]
where $ is the implicit db context that you optionally specify as the first element of :in
(although at that point you don't actually pass in a corresponding db value for it, it's just "for show")all that said, pull
probably is what you want. When you said "the nesting is pretty frustrating" - do you mean the unavoidable outer two levels of #{[...]}
? Crux doesn't implement the complete find spec, which would help a little with that
The below is a closer example to what I'm doing in my project. I could try to sub-query and pull things apart but it's not obvious to me how to do so. I didn't understand what you mean by 'implement the complete find spec'. Can I extend :find to return something other than a set of the findings?
Actually I'm realizing I can use direct equality instead of containment
(q '{:find [e]
:in [n]
:where [[e :x n]]}
re: find spec, I've been using this in my projects:
(defn q [db query & args]
(let [return-tuples (vector? (:find query))
query (cond-> query
(not return-tuples) (update :find vector))
results (apply crux/q db query args)]
(cond->> results
(not return-tuples) (map first))))
If the value of :find
isn't a vector, then it'll wrap the results in (map first ...)
, e.g.
(q db '{:find (pull e [*]) ...})
=> #{{:crux.db/id ...} ...}
If something like this was added into crux that would be wonderfulThe complete edn Datalog find specs include .
and ...
like this https://github.com/tonsky/datascript/blob/master/test/datascript/test/query_find_specs.cljc#L18-L28
Hi there, has anybody ever seen this error:
Warning: resetting Nippy thaw for custom type with id: :crux.codec/edn-id
Warning: resetting Nippy thaw for custom type with id: :crux.codec/id
Exception in thread "clojure.core.async.timers/timeout-daemon" java.lang.IllegalArgumentException: No implementation of method: :exec of protocol: #'clojure.core.async.impl.protocols/Executor found for class: clojure.core.async.impl.exec.threadpool$thread_pool_executor$reify__12555
at clojure.core$_cache_protocol_fn.invokeStatic(core_deftype.clj:583)
at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:575)
at clojure.core.async.impl.protocols$eval142012$fn__142013$G__142003__142020.invoke(protocols.clj:43)
at clojure.core.async.impl.dispatch$run.invokeStatic(dispatch.clj:21)
at clojure.core.async.impl.dispatch$run.invoke(dispatch.clj:18)
at clojure.core.async.impl.channels.ManyToManyChannel.close_BANG_(channels.clj:265)
at clojure.core.async.impl.timers.TimeoutQueueEntry.close_BANG_(timers.clj:41)
at clojure.core.async.impl.timers$timeout_worker.invokeStatic(timers.clj:49)
at clojure.core.async.impl.timers$timeout_worker.invoke(timers.clj:43)
at clojure.lang.AFn.run(AFn.java:22)
at java.lang.Thread.run(Thread.java:748)
I don't think the stack trace is related to Crux, I'm afraid - we don't have any core.async
Ok thanks sounds good for some reason I thought that would be related ...
Hi there, maybe doing it wrong here, but is there a way to "join" entity histories? In other words given a main entity with references, what is the best approach for aggregating all their histories?
Crux's Datalog isn't history aware (currently), so you have to handle it in memory, like so https://github.com/juxt/crux/blob/66896ba1e1cca365d024ab0cb9264bf62db809fe/crux-bench/src/crux/bench/ts_devices.clj#L216-L254 or https://github.com/juxt/crux/blob/66896ba1e1cca365d024ab0cb9264bf62db809fe/crux-bench/src/crux/bench/ts_weather.clj#L292-L347
ok sounds good
Another question about patterns, what if I wanted to match
on an attribute. Would I use a transaction function instead?
is there a magic trick to def functions and try them in the repl before publishing them? I am sure there is 😄
You can use with-tx, or just write the function against a db directly and then port it. Not quite magic...
Actually with-tx
is a good idea - the thing is that tx fns are a bit opaque and difficult to debug - unless I am missing some more advance technique of course