asami

nijssels 2022-04-07T11:26:23.860979Z

Hello, I intend to use Asami in a ClojureScript frontend. The data used in the app contains current and old data (distinguished by timestamps). Is it possible to import/transact that data using those timestamps? Much like Datomic can, using :db/txInstant. (See https://cjohansen.no/annotating-datomic-transactions/ )

quoll 2022-04-07T11:33:59.897839Z

How is the data coming in? Is it structured (as in a seq of Clojure structures) or as edn? Then yes.

quoll 2022-04-07T11:34:48.178699Z

If it's JSON, then there's no schema to tell the transaction function to do that translation

nijssels 2022-04-07T11:39:26.371069Z

Its structured. I pull the data from a Clojure webserver as transitjs. The data is "flat" at that point, as in resembling records from a database. The data might look like (extremely simplified): ID Value Timestamp 1 x yesterday 1 y today 2 z today

nijssels 2022-04-07T11:40:19.408769Z

How can I tel Asami to use those timestamps?

quoll 2022-04-07T13:24:23.706409Z

For the in-memory version (which is what you're using in a browser), Asami just lets you insert them.

quoll 2022-04-07T13:24:53.363989Z

Even on disk (in the JVM), a number of timestamp formats are accepted

nijssels 2022-04-07T15:10:34.096229Z

The point isnt necessarily about reading the timestamp, but later being able to use the timestamps for since/as-of operations.

quoll 2022-04-07T17:50:42.412599Z

The since and as-is functions do not apply to data (they get applied to databases). So I don't know what you're referring to here

Jakub Holý (HolyJak) 2022-04-07T17:42:03.437799Z

So it seems Asami makes it possible to use :id for lookup but does not ensure its uniqueness:

(let [conn ...]
    @(d/transact conn {:tx-data [{:db/id -1 :id [:duplicate-test/id :SAME]}]})
    ; => :tempids {-1 #a/n[24], [:duplicate-test/id :SAME] #a/n[24]}}
    @(d/transact conn {:tx-data [{:db/id -1 :id [:duplicate-test/id :SAME]}]})
    ;  => :tempids {-1 #a/n[25], [:duplicate-test/id :SAME] #a/n[25]}}
    (d/q '[:find ?e :where [?e :id [:duplicate-test/id :SAME]]] conn))
  ; => ([#a/n[24]] [#a/n[25]])
so I guess before I insert anything presumably new I should run a query to verify the :id value is not used. Or is there a better way?

quoll 2022-04-07T17:52:11.698899Z

This comes about because I did not conceive of trying to do the same thing 2 different ways at the same time

quoll 2022-04-07T17:53:20.241279Z

I could try to merge them, though the default approach would be to throw an exception when doing this

quoll 2022-04-07T18:34:09.685879Z

The code for this is asking, "Have you specified the object you're referring to? If so, then is it one that you have specified somewhere earlier in this transaction, or is it already present in the database?" To do this, it looks for identifiers. The first one it looks for is :db/id. You've specified this as a negative number, and it hasn't appeared already in the current transaction, so that says that you need to create a new object. At that point, it doesn't care about :id, because the "which object?" question has been answered. However, the :id field is attached, so it gets stored. In your second transaction, you do it again. You specified :db/id to be a negative number, and it hasn't been seen yet in this transaction, so that means you want a new object. At this point, it doesn't care about the :id, but you did specify it, so it gets stored.

quoll 2022-04-07T18:34:19.122619Z

i.e. It did precisely what you asked of it

quoll 2022-04-07T18:35:42.158589Z

So, what I think I should do here is probably throw an exception if more than one identifier is present. Or, alternatively, if more than one is present, then perhaps I could do a lookup to see if they're consistent with each other

👍 1
Jakub Holý (HolyJak) 2022-04-08T08:09:27.425559Z

Ah, thank you for the explanation! I must admit that it wasn't really clear to me what the relation of the three possible IDs is. Thus I will only use :id and, when I need to refer to the entity inside the transaction, the [:id ...] . Thanks a lot!

quoll 2022-04-07T17:54:17.892659Z

The better way is to not define a :db/id. You have an :id, so you don't need it

👍 1