Fork me on GitHub
#datomic
<
2022-02-23
>
manutter5113:02:41

How can I get datomic to tell me all the transactions that were transacted between start-time and end-time? I’ve gotten as far as

[:find ?e ?a ?v ?op
 :in $ ?log ?start ?end
 :where
 [(tx-ids ?log ?start ?end) [?tx ...]]
 [(tx-data ?log ?tx) [[?e ?a ?v _ ?op]]]]
, but that just gives me
#{[13194272974810 50 #inst "2022-02-22T14:38:18.227-00:00" true]}
How do I get to the actual value that was changed?

favila13:02:42

That is the value that was changed?

favila13:02:16

This appears to be just one empty transaction. Try different start and end parameters to get others

manutter5113:02:34

What does 50 mean in that response?

favila13:02:55

That’s an attribute

favila13:02:31

Likely :db/txInstant

favila13:02:12

Consider using d/tx-range also

favila13:02:52

If all you really want is the full log it will be faster and offers laziness

manutter5113:02:53

Oh snap, that looks like exactly what I’m after, thanks a ton!

manutter5114:02:30

Yeah, I can see everything I’m looking for now, thanks again!

johanatan20:02:55

hi, technically i'm trying the following in datascript, but if there were some fundamental problem with my syntax, I'd hope this channel could spot it. why isn't the keyword mentioned in my predicate being filtered out?

core=> (cljs.pprint/pprint (d/q `[:find [?k ...] :where [?e :root/user ?r][?r ?k ?v][('not= ?k :user/feature-flags)]] @connection))
[:user/id
 :user/disable-global-role?
 :user/has-to-accept-license?
 :user/first-name
 :user/last-name
 :user/feature-flags
 :user/role
 :user/company-id 
 :user/avatar-url 
 :user/app-roles 
 :user/email]
nil
if I try the complement, I get the same result list:
core=> (cljs.pprint/pprint (d/q `[:find [?k ...] :where [?e :root/user ?r][?r ?k ?v][('= ?k :user/feature-flags)]] @connection))
[:user/id
 :user/disable-global-role?
 :user/has-to-accept-license?
 :user/first-name
 :user/last-name
 :user/feature-flags
 :user/role
 :user/company-id 
 :user/avatar-url 
 :user/app-roles 
 :user/email]
nil
is this a problem with datascript or my use of it? (note that if I use = or not= rather than the quoted alternates, it complains that the built-in predicate doesn't exist. so i know it's at least doing some analysis of these predicates-- apparently just not actually running them).

favila20:02:29

In datomic, [?r ?k ?v] would bind a number (the attribute entity id) to ?k

johanatan20:02:04

that would be ?r in my testing with datascript

johanatan20:02:15

but we can see the list of ?k's returned in the result list here and they are keywords

👍 1
favila20:02:43

Could it be some edge case with qualified symbols and predicate clauses?

favila20:02:21

(d/q '[:find [?k ...] :where [?e :root/user ?r][?r ?k ?v][(not= ?k :user/feature-flags)]] @connection)

favila20:02:31

note the quoting changed

favila20:02:04

[?k]` would expand to [current-ns/?k]

favila20:02:48

maybe that ?k isn’t unifying with the one inside the (not= ?k ...) for whatever reason

johanatan20:02:51

Yea I tried ?k# too to remove the ns

johanatan20:02:27

Ok I'll try outer single quote

johanatan20:02:14

oooh, the combination of outer single quote and no quote on the pred fn worked

johanatan20:02:08

core=> (cljs.pprint/pprint (d/q '[:find [?k ...] :where [?e :root/user ?r][?r ?k ?v][(not= ?k :user/feature-flags)]] @connection))
[:user/id
 :user/disable-global-role?
 :user/has-to-accept-license?
 :user/first-name
 :user/last-name
 :user/role
 :user/company-id 
 :user/avatar-url 
 :user/app-roles 
 :user/email]
nil
core=> (cljs.pprint/pprint (d/q '[:find [?k ...] :where [?e :root/user ?r][?r ?k ?v][(= ?k :user/feature-flags)]] @connection))
[:user/feature-flags]
nil

johanatan20:02:03

interestingly i have the following elsewhere in my codebase for query generation and it works (notice the backtick):

(defn query-root-scalar [key]
  `[:find ?v# . :where [~root-id ~(keyword "root" (name key)) ?v#]])

favila20:02:52

oh, it’s because 'not= expands to the quoted form

favila20:02:00

you needed ~'not=

johanatan20:02:26

doh! yep. good call

johanatan20:02:48

so will it hurt anything that all of my ?s will be "namespace-bound"

johanatan20:02:59

I was trying to get fancy by using # suffix to make them unique

favila20:02:31

so it was invoking ('not= x :something) which is symbol-lookup of not= in collection x, or :something as not found, so it was always returning :something thus everything matched.

johanatan20:02:48

I was getting "Unknown predicate error ..." when the predicate wasn't found in bulit-ins linked to above

favila20:02:56

re “weird part”, yeah but it’s actually (quote not=) which isn’t in that list

johanatan20:02:14

right which should produce an "Unknown predicate error ..." 🙂

favila20:02:55

or, it will just eval to itself?

johanatan20:02:50

mm, not sure. my brain is getting twisted at these meta levels. something weird was going on for sure.

favila20:02:08

>  so will it hurt anything that all of my ?s will be “namespace-bound” It’s just weird, you may shake out edge cases

favila20:02:32

It defies the usual assumptions

johanatan20:02:00

yea but that seems to be sort of the SOP in these datascripts

johanatan20:02:23

perhaps going with the flow is called for 🙂

favila20:02:32

https://github.com/brandonbloom/backtick may make it easier to mix quasi-quoting and unqualified symbols

👍 1
johanatan22:02:49

hi, is it possible to do a pull expression with a wildcard / except certain fields? something like the following:

[:find [(pull ?e [* !:this/field]) ... 

johanatan23:02:44

how about the ability to apply a "result transform" to the result of a :find ?

johanatan23:02:14

such as the: into {} portion of the following:

core=> (cljs.pprint/pprint (into {} (d/q '[:find ?k ?v :where [?e :root/user ?r][?r ?k ?v][(not= ?k :user/feature-flags)]] @connection)))

johanatan23:02:49

the library i'm using won't allow the "outside wrapper" transform such as above, so i'd need a way to get it inside the query itself

favila23:02:52

(map #(update % 0 dissoc the-field)) ?

johanatan23:02:49

where would that fit into the overall [:find ... } ?

johanatan23:02:22

actually i don't think that would work. update and dissoc require a map which in my example doesn't exist until into {} is executed

johanatan23:02:06

look at the reg- functions below to understand why any "outer wrapper" solution won't work: https://github.com/denistakeda/re-posh/blob/master/src/re_posh/subs.cljc of course, it could be done with two subs, one taking the input from the first and then transforming it. but imagine that we want to do this for 100s of subscriptions and suddently 250 subs become 500 subs (which is overly verbose)

favila00:02:06

Update doesn’t require a map

favila00:02:16

Is there a reason you don’t enumerate the fields you need?

johanatan00:02:51

yea, verbosity. it's N-1 fields that I need

johanatan00:02:56

and N is on the larger side

johanatan00:02:13

but i think i will just restructure the facts around this data, break it out to the top level

johanatan00:02:17

upon insertion

johanatan00:02:33

which will be fine for this case. but it's unfortunate that there isn't a better solution for this

johanatan00:02:39

in the general case