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.
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?
Some things you say make me wonder if you think there’s some extra magic. Eg your first bullet makes no sense to me
“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
You can think of all three of these as just seek-datoms at bottom; they differ only by where they start and stop seeking
Seek-datoms is the simplest (most flexible but does the least for you). Datoms and index-range are just “easy” wrappers for common cases
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.
Index range is pretty much seek-datoms and take while. (It also makes sure you don’t fall off the A)
What cardinality per EA are you expecting? If it’s under 2000 you probably won’t find any advantage to seeking sub-ranges
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.
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))))
adjust (< v ending-V) to your taste
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