datascript

Immutable database and Datalog query engine for Clojure, ClojureScript and JS
oly 2020-09-08T10:32:40.107100Z

couple of questions can you do sub queries ? using d/q inside an existing d/q errors for me and i can not find any examples πŸ˜•

pithyless 2020-09-11T21:45:44.121800Z

@oliver.marks - just as a followup, TIL that Datomic does also support a syntax for nested queries (it has certain limitations, but still...). No idea if that was ever ported to DataScript. 🀯 https://docs.datomic.com/cloud/query/query-data-reference.html#q

oly 2020-09-14T08:02:46.126800Z

I think i actually saw that at some point, but could not find any examples when i needed it again so thanks for posting it πŸ™‚

oly 2020-09-08T10:35:07.109600Z

0. [ 54 #{ 1371 291 779 1101 734 ... } ]
Also give the above I want to get a couple of attributes from the entity ids in the set and combine them into a string, I think i can do this in a sub query but are there other ways, In the result above i am using distinct but i kind of want distinct grouped fields to work with which I will need to concat together to make strings

oly 2020-09-08T10:38:00.110300Z

:find ?pid (distinct (str ?n1 "-" ?n2)) 
something like that possible perhaps ?

stathissideris 2020-09-08T13:34:26.111100Z

@metasoarous this is what I’ve come up with so far, it almost looks like it would be worth looking into react for swing instead πŸ˜„ https://gist.github.com/stathissideris/7eb2d14990d0b23f8edbee53dbb7bc21

πŸ˜‚ 1
stathissideris 2020-09-10T19:26:37.121100Z

@metasoarous apart from the fact that all of the queries run on every transaction, I also have the problem of hierarchy: if I have a listener for the windows and a listener for updating their contents, this code does not guarantee any order (you need to have created windows to update/add stuff within them)

2020-09-10T19:27:18.121300Z

Hmm...

stathissideris 2020-09-08T13:35:21.111200Z

no attempts to avoid re-running queries, it’s not my main problem anyway β€” updating the UI is

pithyless 2020-09-08T14:06:53.111400Z

@oliver.marks I'm not exactly following your use-case, but whenever you want to run sub-queries, just remember you can run multiple queries (possibly interleaved with data-munging using regular clojure functions); Sub queries like in SQL engines are necessary, because you want queries to be atomic (here you have a derefed immutable value); or to save on networking bandwidth (here your entire working set is already in memory).

oly 2020-09-08T14:29:07.111600Z

should i run these queries separately ? ie (d/q [query]) (d/q [query]) then combine the results some how in my head I would do (dq [query (d/q query entity-id]) ie have a sub query that looks up based on values in the first query

oly 2020-09-08T14:30:43.111800Z

I am finding what i want to do quite complex, i can get half way there but combining is the tricky part, I am pulling a product then combining all combinations of 2 attributes against that record but I want to use a different value when it exists

oly 2020-09-08T14:33:28.112Z

so think one product many prices, but not all prices exist in which case i want the record to be zero, I can select the price eid but this gives me many prices to one product and i need it to be a row ie product [price1 price2 price3] every product needs 3 prices but some may only have a single price entered in which case i should still get the 3 prices and the missing values should be 0

oly 2020-09-08T14:33:56.112200Z

this way i can map over the result set and generate a csv

pithyless 2020-09-08T14:35:08.112400Z

what's the relationship? :price/product or :product/price?

oly 2020-09-08T14:35:13.112600Z

currently i am using distinct which is giving me a product entity and a set of price entities, my plan is to pull on each price entity and perhaps do a map merge to fill in the missing values

oly 2020-09-08T14:35:23.112800Z

:price/product

oly 2020-09-08T14:36:06.113Z

so products do not have a price entity in them

oly 2020-09-08T14:36:26.113200Z

(d/q '[:find ?product-entity (distinct ?e)
         :where [?e :price/product ?product-entity]] @conn)

oly 2020-09-08T14:36:53.113400Z

so I can use that to get a product entity with a set of price entites against each product

pithyless 2020-09-08T14:37:54.113600Z

what about something like?

(d/q '[:find (pull ?e [:product/id {:price/_product [:price/value]}])
       :where [?e :product/id]]
     db)

oly 2020-09-08T14:42:26.113800Z

bear with me while i do some testing πŸ™‚

pithyless 2020-09-08T14:44:02.114200Z

The pull does a reverse-join (but will still return products even if no prices exist); Then you would need to do some data-wrangling on the resultset to get it in a form that you need for your CSV (adding default zeros, etc.)

oly 2020-09-08T14:45:46.114400Z

yeah I might be able to work with this, got a couple of question can you use functions in a pull like you can in a query where

oly 2020-09-08T14:46:09.114600Z

say i want to rename :price/value to be the composite of two other attributes ?

oly 2020-09-08T14:48:11.114800Z

[(?make-keyword ?n ?c ?amount) ?kw]
So i figured out i can do this in a where, this fn just combines n and c into a keyword with amount as the value

pithyless 2020-09-08T14:48:20.115Z

no, that's what I meant about the data munging; You want to use where clauses to filter out the data you're interested; pull to fetch all the data you need to work with; and then clojure to do the data-munging πŸ™‚

(let [results (d/q ...)
      final-results (some-data-munging ...)] ...) 

oly 2020-09-08T14:49:12.115200Z

perhaps that's where i am going wrong trying to do to much in datalog

pithyless 2020-09-08T14:49:17.115400Z

IMO, that kind of stuff only belongs in the where clause if you want to use ?kw for further filtering

oly 2020-09-08T14:50:44.115600Z

okay good to know I was using it then doing (distinct ?kw) to get a set of values against a product with the set being the keyword i actually needed

pithyless 2020-09-08T14:52:41.115800Z

A classic example is sorting:

(let [sorting-data (d/q '[:find ?only ?keys ?used ?for ?sorting ...])
      sorted (sort-by some-fn sorting-data)
      actual-data (d/pull-many [:data :to :view] (map :db/id sorted))])

pithyless 2020-09-08T14:54:18.116100Z

^ notice that the keys you sorted by may not even show up in the pulled data you're interested in

oly 2020-09-08T14:58:09.116400Z

yeah thanks for bearing with me, trying to expand the example to pull in the extra data I need

stathissideris 2020-09-08T17:14:09.116600Z

(refined after working on it a bit)