Clojurians
#datomic
<
2016-08-03
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

zentrope00:08:31

I have an attribute [:foo/bar :ref :many], is there a datalog query that allows me to query for “foo” such that :foo/bar must have three specific refs?

zentrope00:08:53

Seems I can query: find entities that have all the related entities in my param list, or any of the params, but not a subset of the params.

zentrope05:08:45

To clarify, I want to write a query like “find all the clubs in which “bill” “fred” and “sue” are members.

yonatanel06:08:46

@zentrope: can you show the two queries you mentioned that are not quite what you want? "all related entities" and "any of the params"

zentrope06:08:33

I ended up just dynamically generating the query.

zentrope06:08:31

[[?e :class/students [:student/id “ted”]] [?e :class/students [:student/id “fred”]] something like that.

zentrope06:08:07

(q [:find ?e :in $ [?students …] :where [?e :class/students ?students]] db [“ted” “fred”])

zentrope06:08:37

That gives me all the classes where either ted or fred is a student.

zentrope06:08:46

And of course finding the classes where “ted” is a student is trivial. (That’s the “any one of” the params.)

zentrope07:08:31

My solution is to just take the vector of names and generate clauses for each one, thus creating the “and” condition. I sort them so that query caching has a chance.

yonatanel07:08:29

@zentrope: just an idea, add a (count ?students) and :with ?students (not sure if you need that actually), and later keep only the results which has count equal to input students

robert-stuttaford12:08:36

@zentrope assuming the need for exactly 3 is fixed:

(d/q '[:find ?foo :in $ [?bar1 ?bar2 ?bar3] :where
       (and [?foo :foo/bar ?bar1]
            [?foo :foo/bar ?bar2]
            [?foo :foo/bar ?bar3])]
     db ["one" "two" "three"])

robert-stuttaford14:08:15

anyone using http://www.terraform.io and Datomic together? @marshall, do you know if this has been done? i'm guessing it's fairly straightforward, if one uses your AMI

marshall14:08:15

@robert-stuttaford: I’ve not heard of anyone using it. Is it supposed to take the place of e.g. CF?

fenton15:08:33

Noob question: How do people programmatically interact with datalog? I dont want to always hard code all my queries, I'd like to parameterize it somehow. Any blogs or suggestions. Do people use macros for this. I haven't got into macros myself yet fwiw.

marshall15:08:13

@fenton: are you using Clojure?

marshall15:08:28

the great thing about queries is they are just data

marshall15:08:34

you don’t have to use macros to generate them

marshall15:08:15

you can generate each element of a query as members of a map

fenton15:08:40

ok, let me read and I'll come back if not understood. thx! :slightly_smiling_face:

fenton15:08:43

I guess what I'm wondering is could a datomic query be parameterized in a function like so: (defn generic-find [data] (d/q 'data (get-db)))

fenton16:08:05

I'm a big confused about how to programmatically work with a quoted map.

fenton16:08:23

I think i figured it out:

fenton16:08:10

instead of quoting all the datalog, just quoting the bits I didn't want evaluated.

mlimotte16:08:41

@fenton: you can also use syntax quoting (`) and unquote (~) which can be more convenient: `{:find [[?ent ...]] :where [[?ent :type ~type]]}

fenton16:08:22

oh that looks nice!

mlimotte16:08:24

also, you should have a namespace for the :type attribute

fenton16:08:00

can u give a short explanation why it needs to be namespaced?

fenton16:08:50

does it become like a global keyword or something otherwise?

fenton16:08:24

it seems to work without the namespacing.

fenton16:08:08

@mlimotte: f--king cool! omg! sorry had to share my enthusiasm about finally understanding the use of this stuff! :slightly_smiling_face:

mlimotte17:08:21

without namespace, it's all global. the namespace helps to organize things. best practice.

fenton17:08:43

@mlimotte: ok cool thanks.

robert-stuttaford17:08:45

@fenton, be aware that d/q does computation to prepare queries (its first arg) and caches that work using the query value itself as a key. so if you generate them dynamically, you could be generating unnecessary work for d/q. i recommend seeing if you can parameterise with :in, first.

fenton17:08:37

@robert-stuttaford: ok. i had some where clause 'datoms' that were being used over and over, so I pulled those out to keep it DRY. I wonder if that will cause a cache miss. Hmmm... Wonder how to tell what gets cached.

robert-stuttaford18:08:10

@fenton: datalog rules :slightly_smiling_face:

robert-stuttaford18:08:46

rules is a noun, there, not a verb :slightly_smiling_face:

robert-stuttaford18:08:44

@fenton, here's a fairly concise example (using datascript) https://github.com/robert-stuttaford/stuttaford.me/blob/master/src/stuttaford/client/components/codex.cljs#L20-L52 see it in action http://www.stuttaford.me/codex view the source of the page to see the data

robert-stuttaford18:08:11

note the % in the :in clause

fenton18:08:35

@robert-stuttaford: ok, let me read and try to grok that... looks promising.

fenton18:08:46

@robert-stuttaford: so cool!

zentrope21:08:31

I bet a lot of folks will appreciate the use of the log API in the in-memory version of the DB.

zentrope21:08:52

@robert-stuttaford: Thanks! The problem is that I don’t have a fixed size. Instead, I just generate the where-clauses dynamically. The end result looks just like your version, more or less.