datascript

Immutable database and Datalog query engine for Clojure, ClojureScript and JS
oly 2020-08-26T11:32:56.012300Z

is there anything built in to flatten nested data, so when looking up refs in a pull query it returns the refs as sub hashmaps when i have a single key value can i flatten or should I do that afterwards ?

pithyless 2020-08-27T08:43:51.012700Z

datomic has :xform option in pull-api, but I don't think that has been ported to datascript. Even so, you would need to apply that to each ref individually. One way is to clojure.walk/postwalk over the result and replacing all the known refs with their idents. You can either explicitly pass in the refs you need replaced or you can find all the refs automatically by querying the schema (or in the case of datascript - the initial schema map).

pithyless 2020-08-27T08:45:04.012900Z

Fulcro RAD has some code that could serve as a good starting point (it considers both multiple and single cardinality): https://github.com/fulcrologic/fulcro-rad-datomic/blob/develop/src/main/com/fulcrologic/rad/database_adapters/datomic.clj#L80-L102

pithyless 2020-08-27T08:46:05.013300Z

I prefer the postwalk approach, because it makes the conversion explicit and doesn't confuse data querying with data mangling 🙂

Casey 2020-08-27T08:50:42.014Z

Woah, I joined this channel with the intent of asking this exact question..

Casey 2020-08-27T08:51:23.014200Z

I'm working with the learndatalog and kristianmandrup's tutorial at https://github.com/kristianmandrup/datascript-tutorial/blob/master/pull_data.md#pull-and-query-combined

Casey 2020-08-27T08:51:43.014500Z

The latter says I should be able to (d/pull-many db '[*] (d/q '[:find ?e :where [?e]]))

Casey 2020-08-27T08:52:41.015100Z

But there seem to be multiple things wrong with this: 1. You need to pass the db to the query function 2. The result of the query is a set of 1 element vectors that pull-many choke son

Casey 2020-08-27T08:54:12.015300Z

There's got to be something simple going wrong here?

Casey 2020-08-27T08:56:39.015600Z

This works, but seems like it should be unnecessary (d/pull-many @conn '[*] (flatten (vec (d/q '[:find ?e :where [?e]] @conn))))

pithyless 2020-08-27T09:01:08.016Z

1. Yes, you want to learn to pass an immutable db around to queries, not derefing an unkown state conn. 2. You're right about the set of tuples, but there is more sugar syntax: [:find ?e] vs [:find ?e .] vs [:find [?e ...]] (what you're looking for) 3. Fetching all data like this seems like an unusual use-case; and if you want all eids, you can probably just take that straight out of the indices.

Casey 2020-08-27T09:06:59.016200Z

😮 I always assumed the ... in examples was just the author eliding stuff that wasn't important, not that it was literal syntax.

Casey 2020-08-27T09:08:21.016400Z

agreed regarding #3, I'm just finding my way around datalog, and after putting stuff in a natural question is how do I get it all out?

Casey 2020-08-27T09:11:57.016600Z

thanks @pithyless your "domain modeling with datalog" talk got me here 🙂

🤘 1
oly 2020-08-27T09:15:03.016900Z

thanks for that, not liking these nested replies I missed the replies till now 😕

oly 2020-08-27T09:15:42.017100Z

but you have given me a few options to look into, think i need to make notes as I go and make a post about these things 🙂

pithyless 2020-08-27T09:16:04.017300Z

ad 3. that's why it unusual - asking for "all" the data hardly ever comes up in practice; unless you want to serialize/backup/etc, and then it's probably more practical to use d/datoms d/seek-datoms d/history etc.

oly 2020-08-27T09:16:56.017500Z

currently I am making a query to grab data and make a csv files from the results

oly 2020-08-27T09:18:20.017700Z

I ended up specifying each entity in the query instead of using pull inside d/q with the [*] wild card

Casey 2020-08-27T09:37:25.029100Z

@pithyless regarding #1, makes sense and is something I'm already used to when working with state maps, however is it possible to transact in datascript without involving the atom? that is I want a function to take db value, and return an updated db value. datacript's transact! only operates on a connection.

cjsauer 2020-08-28T13:21:06.040900Z

@ramblurr have a look at d/with and d/db-with. Those both allow you to incorporate new datoms into a database as a pure function of db->db