Fork me on GitHub
#datomic
<
2017-06-14
>
val_waeselynck06:06:14

@devth they can't, and you can definitely benefit from the client itself having some notion of a tempid. Note than you can also use unique-identity attribute for upsert, e.g {:a/id "some-id" :a/b {:b/id "some other id"}} instead of {:a/id "some-id" :a/b [:b/id "some other id"]}

val_waeselynck06:06:53

Be careful of the security issues that can be caused by sending that from the client though

devth14:06:07

val_waeselynck: thanks. you mean client as in browser? in my case i'm sending them from the server side of a peer.

val_waeselynck20:06:57

Yes as in browser

devth20:06:02

got it. thanks

cap10morgan14:06:48

How would one query Datomic for any entities where attr1 has value a OR attr2 has value b? I can't use an or clause because the attrs are different. I feel like I might be missing something simple here.

jeff.terrell15:06:12

Not sure if this is the best solution, but you could always do two queries and combine the results afterwards.

cap10morgan15:06:46

@jeff.terrell Yeah. That's my fallback option. I'm just surprised that there is (apparently) no way to do this in one query.

karol.adamiec15:06:12

@cap10morgan are you absolutely sure or clause is not what you need? i do use it with different attrs….. ??

karol.adamiec15:06:53

it seems to me like it is is EXACTLY for that reason. on one attr you can have logical or by binding a collection

cap10morgan15:06:57

@karol.adamiec I got an error when I tried and the docs say: "All clauses used in an or clause must use the same set of variables, which will unify with the surrounding query. This includes both the arguments to nested expression clauses as well as any bindings made by nested function expressions."

karol.adamiec15:06:36

so the issue is in binding ;/

cap10morgan15:06:40

but maybe I'm doing it wrong 🙂

karol.adamiec15:06:47

so OR claus works for :attr1 :attr2 only when it is bound to the same variable a

karol.adamiec15:06:09

seems like two queries then 😞

favila15:06:50

@cap10morgan show us the clauses. You probably need or-join

favila15:06:18

the key is "same set of variables" (for unification), NOT same attributes

cap10morgan15:06:45

ah, so maybe (or-join [?user] ...?

cap10morgan15:06:34

hey, that seems to work. thanks @favila!

cap10morgan16:06:58

oh, huh. it looks like the or-join version does not work. it finds every user b/c the ?email-search and ?phone vars don't get unified with their inputs I guess?

cap10morgan16:06:37

so the relation binding version might be the way to go

favila16:06:54

(d/q '{:find  [[(pull ?user [*]) ...]]
       :in    [$ ?email-search ?phone]
       :where [(or-join [?user ?email-search ?phone]
                 [?user :user/email-search ?email-search]
                 [?user :user/phone ?phone])]}
  (d/db c) "" "+14055556666")

cap10morgan16:06:43

huh, I would have thought that was what it was doing w/o or-join

favila16:06:12

or adds the additional restriction of all clauses using the same vars

favila16:06:29

I'm not sure if that's just for safety or for an optimization

cap10morgan16:06:19

Now I'm wondering which one I prefer. Do you prefer the or-join over the relation binding, @favila?

favila16:06:41

explicit or-join is the only thing you can do if you have to check more than one pattern to match a condition

favila16:06:03

e.g., if you grow a "contact" entity and move all phone and email into those

favila16:06:27

or-join is probably also faster, since the query compiler can see what attrs it needs to look up

favila16:06:39

(although I don't know if it's fast enough to make a difference)

favila16:06:53

I would only use the relation biding form if I needed its generality

favila16:06:47

i.e., I had a set of different attributes I could match on, all attrs are on the same entity, and my searches could have one or many in any combination

cap10morgan16:06:07

yeah, makes sense. thanks!

favila16:06:28

so, my decision for one or the other is driven by interface more than anything

souenzzo19:06:03

What (performance) concerns should I have when using ground?

favila19:06:20

how are you using it?

souenzzo19:06:32

Two uses: - {:find [?name-e ?e] :where [[(ground (quote ?e)) ?name-e] ...(stuff)...]} - To know the "name" of each match - {:find [?e] :where [[(ground 12313) ?e] ...]} - To force the match to occur in a specific entit(ies) In general, these 2 uses at the same time. Queryies, with ground at begin of where, are taking ~100ms on an "empty"(very small background), mem, db.

favila19:06:56

how does that first one work?

favila19:06:18

ground is supposed to take literals, so the value of ?name-e is either (quote ?e) (a list) or ?e (a symbol)

favila19:06:54

I am interested in how you use it in (stuff) because I can't think how that would work

favila19:06:40

the second case you could make ?e input to the query?

favila19:06:47

but that is a legit use and I don't think any other way of getting ?e and its value at the same time would be faster

favila20:06:58

(d/q '[:find ?xv . :where [(ground (quote ?x)) ?xv]]) ;=> ?x @souenzzo

souenzzo20:06:10

{:find  [?e688269 ?e
          ?stage1688270 ?stage1
          ?stage2688271 ?stage2
          ?date-close688272 ?date-close
          ?date-open688273 ?date-open]
  :where [[(ground 17592186046417) ?stage2]
          [(ground #inst"2017-11-29T20:44:21.770-00:00") ?date-close] ;;**
          [(ground (quote ?e)) ?e688269]
          [(ground (quote ?stage1)) ?stage1688270]
          [(ground (quote ?stage2)) ?stage2688271]
          [(ground (quote ?date-close)) ?date-close688272]
          [(ground (quote ?date-open)) ?date-open688273]
          [?e :stage-container/calendar ?stage1]
          [?e :stage-container/calendar ?stage2]
          [?stage1 :calendar/stage-type :stage-type/a]
          [?stage2 :calendar/stage-type :stage-type/b]
          [?stage1 :calendar/close ?date-close]
          [?stage2 :calendar/open ?date-open]]}
It's automatically generated....

souenzzo20:06:11

On ;;**, it's auto generated basead on other query. I dont know what results are entities-id, what are values...

favila20:06:42

well, it seems a little weird, but it does what you intend

souenzzo20:06:00

favila: works! 😄 But its slow 😞

favila20:06:26

so if you remove the grounds, and leave all else the same, it runs faster?

favila20:06:03

'{:find  [?e
          ?stage1
          ?stage2
          ?date-close
          ?date-open]
 :where [[(ground 17592186046417) ?stage2]
         [(ground #inst"2017-11-29T20:44:21.770-00:00") ?date-close]
         [?e :stage-container/calendar ?stage1]
         [?e :stage-container/calendar ?stage2]
         [?stage1 :calendar/stage-type :stage-type/a]
         [?stage2 :calendar/stage-type :stage-type/b]
         [?stage1 :calendar/close ?date-close]
         [?stage2 :calendar/open ?date-open]]}
for example

favila20:06:15

It's probably slow because of clause ordering, not grounds

favila20:06:36

you are looking at all ?e which have :stage-container/calendar attribute

souenzzo20:06:59

Removing "label grounds", (dotimes [i 1000]), goes from 3s to 2s. A single query on repl, is 10x faster then "on integration test" 😕

souenzzo20:06:39

I'm going it on a d/with db-after ("on code")... But I think that should not be relevant..

favila20:06:09

something is fishy with your tests

favila20:06:31

you are either redoing work, or your data makes the bad clause ordering more painful

favila20:06:26

this is closer to optimal:

favila20:06:29

[?e :stage-container/calendar ?stage2]
         [?stage2 :calendar/stage-type :stage-type/b]
         [?e :stage-container/calendar ?stage1]
         [?stage1 :calendar/stage-type :stage-type/a]
         [?stage1 :calendar/close ?date-close]
         [?stage2 :calendar/open ?date-open]

favila20:06:25

if date-close is even more selective, that might be even more optimal

favila20:06:30

to put it higher

favila20:06:53

writing it by hand I would do this. (I might reorder the clauses if I knew more about the schema):

'{:find  [[(pull ?e [:db/id
                    {:stage-container/calendar
                     [:calendar/open
                      :calendar/close
                      {:calendar/stage-type [:db/ident]}]}]) ...]]
  :in    [$ ?stage2 ?date-close]
  :where [[?stage2 :calendar/stage-type :stage-type/b]
          [?stage1 :calendar/close ?date-close]
          [?stage1 :calendar/stage-type :stage-type/a]
          [?e :stage-container/calendar ?stage2]
          [?e :stage-container/calendar ?stage1]]}

wei23:06:19

I’m trying to write a query that checks whether a condition is sufficient for the last 4 out of 7 days. any suggestions on how to structure the datalog?

souenzzo00:06:11

wei:

'{:find  [(count ?day) .]
  :in    [$ ?e]
  :where [[?e :all/days ?day]
          [?day :my/attr ?attr]
          [(> ?attr 10)]
          ]}

wei00:06:38

thanks for the example. guess the problem was a bit underspecified but your link helped

wei23:06:35

I have a workaround.. I can just run my condition query 7 times. but I’d appreciate any suggestions for a more efficient solution!