datomic

braai engineer 2025-10-27T12:51:21.815419Z

Given a multi-cardinality heterogeneous tuple :my/tuple with :db/tupleTypes [:db.type/ref :db.type/keyword :db.type/ref] stored on an entity with ID subject-eid, is there a way to get the performance and flexibility of d/index-range over the tuple values stored for that entity? • Or, do I need to prefix the tuple value of eid to use d/index-range and get better index distribution over :avet? • Or should I use (d/seek-datoms db :eavt subject-eid :my/tuple [starting-ref1 starting-keywords starting-ref2])? I'm not sure seek-datoms supports starting tuple values and the documentation is thin. • Or would (d/datoms db :eavt subject-eid :my/tuple) yield similar performance as d/index-range? d/datoms has slightly more overhead as I understand, but reverse access is desirable.

favila 2025-10-27T13:09:58.794079Z

Knowing these two things: Index range reads avet (exactly the same as seek-datoms avet, just easier to use), and tuples are just like other values wrt collation. Does that answer your questions?

favila 2025-10-27T13:11:03.584099Z

Some things you say make me wonder if you think there’s some extra magic. Eg your first bullet makes no sense to me

favila 2025-10-27T13:13:25.638209Z

“D/datoms has slightly more overhead” no, it’s just as lazy as seek-datoms and index range. However it may start seeking at a spot you don’t want

favila 2025-10-27T13:14:13.734639Z

You can think of all three of these as just seek-datoms at bottom; they differ only by where they start and stop seeking

favila 2025-10-27T13:15:18.977139Z

Seek-datoms is the simplest (most flexible but does the least for you). Datoms and index-range are just “easy” wrappers for common cases

braai engineer 2025-10-27T13:22:14.725209Z

Re: first bullet, what I meant was, is that since (d/index-range db :my/tuple [...] [...]) queries over :vaet I'd need to have the :e in the tuple value if I wanted to use d/index-range, but that's obviously silly because I should just read from :eavt. I wasn't sure how to use use d/datoms to read from an offset in index ala start in index-range. Can I pass start-tuple value to d/datoms or only to d/seek-datoms? Only d/index-range describes start & end, but reading docs for seek-datoms, I see that: > Note that, unlike the datoms function, there need not be an exact match on the supplied components. > The iteration will begin at or after the point in the index where the components would reside. Reversibility would be nice. It seems like seek-datoms over :eavt does what I want. Is index-range just seek-datoms + take-while given end value? Curious to know how index-pull can scan index in reverse order.

favila 2025-10-27T13:29:55.606909Z

Index range is pretty much seek-datoms and take while. (It also makes sure you don’t fall off the A)

favila 2025-10-27T13:32:14.033659Z

What cardinality per EA are you expecting? If it’s under 2000 you probably won’t find any advantage to seeking sub-ranges

braai engineer 2025-10-27T13:41:50.551519Z

It's for EACL, so it depends: cardinality can be large (>100k), but in most typical use-cases will be <10k and often <1k. A user can easily lookup-resources for >=1M terminal resources, but these resources are lazily merged & deduped from many intermediate parallell calls to d/index-range (at present), each of which typically yields <2k datoms. So even though cardinality is typically <2k, I'd like to conserve memory & I/O.

favila 2025-10-27T13:45:18.884379Z

well if the requirement is to extract some contiguous tuple V subrange of datoms with common E+A, then you want (->> (d/seek-datoms db :eavt E A starting-V-tuple) (take-while (fn [[e a v]] (and (== E e) (== A a) (< v ending-V))))

👍 1
favila 2025-10-27T13:45:30.363419Z

adjust (< v ending-V) to your taste

favila 2025-10-27T13:47:09.082579Z

when constructing starting-V-tuple , know that nil in a tuple component sorts before any other value, so e.g. [1 nil nil] starts seeking immediately before the first value whose first slot starts with 1

👍 1