Fork me on GitHub

Whats the idiomatic way to use a previous value as the argument to the next value? Say i want to update all the people with name “drew” to “drew rocks” or “drew” + “something” 6 :person/name “drew rocks” evening 6 :person/name “drew” morning


i can query for the entity id and name then use those in a transact.


@U0DJ4T5U1 I assume the challenge here is to do it without race conditions? In that case, the way to go is to use a transaction function (, e.g [[:myapp/replace-first-name "drew" "drew rocks"]].


If you're using Datofu (, you can use the more general :datofu.utils/datalog-add transaction function, which acts as a Datalog interpreter, so that you don't have to create and install a custom transaction function. E.g:

  '[:find ?e ?a ?new-name :in $ ?old-name ?new-name :where
    [(ground :user/first-name) ?a]
    [?e ?a ?old-name]]
  ["drew" "drew rocks"]]]


What is the justification for reverse reference of multi-arity "component" attributes returning only a single value in a datomic pull? Is there any way to return all the values? Relevant doc:


The justification is that a component attr should always be the only way to reach its entity value


Otherwise it’s not truly a component


@U4XHJ3J9H you can do this

(let [db (d/db conn)
      {:keys [db-after]} (->> (d/q '[:find ?op ?e ?a ?v
                                     [(ground :db/retract) ?op]
                                     [(ground :db/isComponent) ?a]
                                     [?e :db/isComponent ?v]] db)
                              (d/with db))]
  (d/pull db-after [:your/_pattern] eid))


@U2J4FRT2T Not sure about what is being achieved by the code snippet. Can you please explain it to me?


This removes all isComponent annotations, writes it to a local (I.e. forked) db, then pulls from that db

👍 1

In essence, temporarily un-isComponent-ing all attributes so a reverse pull will always be cardinality many


datomic ♥️


Is there an idiomatic way to not do the transaction if key-value did not change? now it does not duplicate fact assertion, but still generates a transaction datom. It sounds like a tiny optimization, but, for example, for .csv file imports, if I want to have more granular error reports, I would not be able to put all the lines into a single transaction, I'd need to batch them. But that would "waste" 1 datom per batch even if batch changed nothing in DB. Smaller the batches – higher the chance of wasting precious datoms on repetitive (large) files imports. Especially, if I will put some meta info about file import in tx.


does :db/noHistory reduce datoms count over time, or somehow just reduces space, and that's it?


is it backed up by excision under the hood?


Has anybody successfully accessed Datomic Cloud across peered VPCs? Our app uses another service that requires VPC peering, and the same procedures do not work when applied to Datomic.


@misha maybe you can avoid the empty transaction altogether w/ a transaction function by running a query on the transactor - that could negatively impact your transactor though, possibly more than just having the empty tx


@hcarvalhoaves yeah, thought about that, and would need to evaluate incoming files frequency vs amount of empty tx-datoms generated. However, transactions would contain fairly large nested maps, and comparing those with db data inside a transaction would likely be slower than I'd like it to be.


on the other hand, looking at error types which make tx fail, those are either network or dev errors: connection reset/timeout, and invalid value type. Which means, with enough testing, ETL step can collect batch of valid tx data from ~1k rows for a single transaction.


speaking of errors. I'd be delighted to see actual value, attribute and it's type in ExceptionInfo data map:

datomic.impl.Exceptions$IllegalArgumentExceptionInfo: :db.error/wrong-type-for-attribute Value 1 is not a valid :bool for attribute :foo/bar?
    data: #:db{:error :db.error/wrong-type-for-attribute}
From the error above you cannot tell that 1 was in fact string "1".

Peter Wilkins22:05:20

Hi all, just learning Datomic. Having a lot of fun. However have hits 2 queries I need a bit of help with: 1: get name and id for topics not in category

(defn orphaned-topics [conn]
  (d/q {:query '[:find [(pull ?topics [:topic/name :topic/id]) ...]
                 :in $ ?taxonomy
                 :where [?t]
                 [?tax :taxonomy/id ?taxonomy]
                 [?tax :taxonomy/categories ?cats]
                 (not [?cats :category/topics ?t])]
        :args  [(d/db conn) "z5ojxcs40azi"]}))
Error message is “Only find-rel elements are allowed in client find-spec”. I don’t understand what a find-rel is. 2: full text search returns a 500 server error after a long delay
(defn search-keywords [conn query]
  (d/q {:query '[:find ?entity ?name ?tx ?score
                 :in $ ?search
                 :where [(fulltext $ :keyword/phrase ?search) [[?entity ?name ?tx ?score]]]]
        :args  [(d/db conn) query]}))
CompilerException clojure.lang.ExceptionInfo: Server Error {:datomic.client-spi/request-id “f90939d2-b6f2-4c55-a8e3-18af3fa7e0b5", :cognitect.anomalies/category :cognitect.anomalies/fault, :cognitect.anomalies/message “Server Error”, :dbs [{:database-id “0ed6aab0-5e31-400f-8fd7-dc40dc67df98", :t 11, :next-t 12, :history false}]} Relevent schema:
#:db{:ident :category/id, :valueType :db.type/string, :cardinality :db.cardinality/one :unique :db.unique/identity}
      #:db{:ident :category/name, :valueType :db.type/string, :cardinality :db.cardinality/one}
      #:db{:ident :category/topics, :valueType :db.type/ref, :cardinality :db.cardinality/many}
      #:db{:ident :category/weight, :valueType :db.type/float, :cardinality :db.cardinality/one}
      #:db{:ident :keyword/excludes, :valueType :db.type/string, :cardinality :db.cardinality/many, :fulltext true}
      #:db{:ident :keyword/phrase, :valueType :db.type/string, :cardinality :db.cardinality/one, :fulltext true}
      #:db{:ident :taxonomy/categories, :valueType :db.type/ref, :cardinality :db.cardinality/many, :isComponent true}
      #:db{:ident :taxonomy/editable, :valueType :db.type/boolean, :cardinality :db.cardinality/one}
      #:db{:ident :taxonomy/id, :valueType :db.type/string, :cardinality :db.cardinality/one :unique :db.unique/identity}
      #:db{:ident :taxonomy/name, :valueType :db.type/string, :cardinality :db.cardinality/one}
      #:db{:ident :taxonomy/organization, :valueType :db.type/ref, :cardinality :db.cardinality/one}
      #:db{:ident :taxonomy-input/categories, :valueType :db.type/ref, :cardinality :db.cardinality/many}
      #:db{:ident :taxonomy-input/name, :valueType :db.type/string, :cardinality :db.cardinality/one}
      #:db{:ident :topic/document-count, :valueType :db.type/long, :cardinality :db.cardinality/one}
      #:db{:ident :topic/id, :valueType :db.type/string, :cardinality :db.cardinality/one, :unique :db.unique/identity }
      #:db{:ident :topic/keywords, :valueType :db.type/ref, :cardinality :db.cardinality/many, :isComponent true}
      #:db{:ident :topic/name, :valueType :db.type/string, :cardinality :db.cardinality/one, :fulltext true}
      #:db{:ident :topic/type, :valueType :db.type/ref, :cardinality :db.cardinality/one}
      #:db{:ident :topic-type/company}
      #:db{:ident :topic-type/risk}
Thanks for reading!


1- pass db, not conn to your functions. db is immutable 2- pull ?topics but mathing :category/topics ?t 3- not sure if fulltext is avaible at datomic cloud