This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-03
Channels
- # admin-announcements (2)
- # alda (4)
- # beginners (15)
- # boot (89)
- # cljs-dev (88)
- # cljsrn (75)
- # clojure (149)
- # clojure-belgium (16)
- # clojure-france (2)
- # clojure-greece (6)
- # clojure-russia (108)
- # clojure-spec (39)
- # clojure-taiwan (3)
- # clojure-uk (7)
- # clojurescript (70)
- # css (3)
- # cursive (17)
- # data-science (2)
- # datascript (7)
- # datomic (41)
- # dirac (3)
- # hoplon (12)
- # instaparse (1)
- # juxt (3)
- # lambdaisland (9)
- # mount (4)
- # off-topic (6)
- # om (71)
- # om-next (4)
- # onyx (22)
- # other-languages (56)
- # perun (15)
- # proton (6)
- # re-frame (32)
- # reagent (42)
- # specter (34)
- # spirituality-ethics (7)
- # tmp-json-parsing (5)
- # untangled (13)
- # vim (4)
- # yada (6)
hey, I’m very new to datomic, and I’m trying to set up an auto incrementing field (I need a serial id for reference). I get the general idea of database functions, but how can I set up a field to be auto incrementing? Can anyone point me to a beginner friendly resource? 😄
depending on the constraints you need for this number, perhaps the db/id itself may suffice
you could keep an entity to control the sequential generation, always keeping the current value, and calling inc in a transaction fn alongside with persisted the incremented value at the entity using it (and also updating the value at the control entity).
a function I use to generate order numbers: (let [new-number (d/q ' [:find (max ?number) . :in $ :where [_ :order/number ?number]] db)] [{:db/id eid, :order/number (inc (or new-number 0))}])
my experience with using max for high insertion volumes is not so good 😕
having a control entity helped tremendously - although it’s not sharding-proof, for this case we plan on using zookeeper.
@viniciushana: shouldn't that attribute be indexed so max would be pretty instant?
@bendy, the idea would be to transact a transaction that uses this fn, rather than setting :order/number
directly
even indexed, for hundreds of thousands of entities a day, it takes more than 20 seconds to run a max
we keep those sequentials unique
the other option is to remember the highest order number in an entity somewhere
yep, and I also recommend to keep it accessible by a :db/ident to ease retrieving it
that's what I would do too
@bendy so in practical terms you’ll want the transactor fn to be like: 1 - lookup the control entity 2 - call inc on the attribute you keep as a sequential control 3 - return the tx vector asserting the business entity with the incremented sequential + a db.add for asserting the incremented sequential attribute at the control entity
just to make sure, this is what I’ve come up with so far - is this what you’re suggesting?
{:db/id #db/id[:db.part/db]
:db/ident :invoice/next
:db/valueType :db.type/long
:db/cardinality :db.cardinality/one
:db/doc "Next invoice number"
:db/noHistory true
:db.install/_attribute :db.part/db}
{:db/id #db/id [:db.part/user]
:invoice/next 1}
{:db/id #db/id [:db.part/user]
:db/ident :number
:db/doc "Function that returns the next id for an invoice."
:db/fn #db/fn {:lang "clojure"
:params [db id]
:code (let [[e n] (datomic.api/q '[:find [?e ?n]
:where [?e :invoice/next ?n]]
db)]
[[:db/add id :invoice/number n]
[:db/add e :invoice/next (inc n)]])}}
I also ask because I’m getting an error and I can’t seem to figure out why… still debugging
no .
, but you do want find single tuple from here: http://docs.datomic.com/query.html#find-specifications
as soon as I add datomic as a dependency to the peer, logging in other parts of the application starts to break. I have configured leiningen as instructed here http://docs.datomic.com/configuring-logging.html
without datomic
(log/error (ex-info "oo" {:a 1 :b 3}) "aaa")
Jun 03, 2016 3:32:40 PM clojure.tools.logging$eval420$fn__425 invoke
SEVERE: aaa
clojure.lang.ExceptionInfo: oo {:a 1, :b 3}
at clojure.core$ex_info.invokeStatic(core.clj:4617)
at clojure.core$ex_info.invoke(core.clj:4617)
with datomic & logback
(log/error (ex-info "oo" {:a 1 :b 3}) "aaa")
=> nil
19576820 2016-06-03 15:39:40,202 [nREPL-worker-1] ERROR user - aaa
- clojure.lang.ExceptionInfo: oo
at clojure.core$ex_info.invokeStatic(core.clj:4617)
at clojure.core$ex_info.invoke(core.clj:4617)
It is a problem with logback (pattern:
%date{ISO8601} [%thread] %-5level %logger{36} - %msg%n %ex{full}
) But why does a lein repl without logback print it properly then?got everything working, updated my snippet with the working code, thanks everyone for your help!
I know that clojure.lang.ExceptionInfo
includes data
in its toString
implementation but not its getMessage
.
It looks like Logback only uses getMessage
and the stack trace in its default exception printer.
@stijn: Whatever logging framework is active in your standalone REPL (maybe java.util.logging) must be printing the ExceptionInfo with toString
.
@stuartsierra: thanks I'll try with another logging backend, or get logback to use toString