barrel_ngram_postings_positional (barrel_ngram v0.9.0)
View SourcePositional (phase-2) posting-list codec: like barrel_ngram_postings, but per ordinal it stores the byte offsets where the gram occurs, not just the ordinal itself.
On disk: [DocCount:varint]([OrdinalDelta:varint][OffsetCount:varint] [OffsetDelta:varint]*OffsetCount)*DocCount, both deltas ascending.
Reading is cursor-based: intersecting two blocks by lockstep merge-join (advance whichever side has the smaller ordinal, decode offsets only when both agree) never materializes either block in full. decode/1 is cursor/1 drained to a list.
distance_check/4 merge-joins two grams at known literal offsets d1/d2, keeping an offset pair only if its document-space distance matches the grams' literal-space distance (off2-off1 =:= d2-d1) -- a candidate match start at off1-d1, still subject to verification. single_gram_candidates/2 is the same off-d math for one gram. Both reject a negative start.
Summary
Functions
A cursor positioned before the first entry of a positional block.
Decode a positional block back to [{Ordinal, [Offset]}], ascending by ordinal, each offset list ascending.
Candidate match starts common to both blocks -- see the moduledoc. Ascending by ordinal; each ordinal's starts are ascending and deduplicated.
Encode [{Ordinal, [Offset]}] as a positional block. Entries need not be pre-sorted; a duplicate ordinal has its offset lists merged rather than one silently overwriting the other.
The next {Ordinal, Offsets, Cursor}, or done.
The one-gram case: every offset of Block's gram is itself a candidate start (off - D). Same negative-start rejection as distance_check/4.
Types
-opaque cursor()
-type offset() :: non_neg_integer().
-type ordinal() :: barrel_ngram_postings:ordinal().
Functions
A cursor positioned before the first entry of a positional block.
Decode a positional block back to [{Ordinal, [Offset]}], ascending by ordinal, each offset list ascending.
-spec distance_check(binary(), non_neg_integer(), binary(), non_neg_integer()) -> [entry()].
Candidate match starts common to both blocks -- see the moduledoc. Ascending by ordinal; each ordinal's starts are ascending and deduplicated.
Encode [{Ordinal, [Offset]}] as a positional block. Entries need not be pre-sorted; a duplicate ordinal has its offset lists merged rather than one silently overwriting the other.
The next {Ordinal, Offsets, Cursor}, or done.
-spec single_gram_candidates(binary(), non_neg_integer()) -> [entry()].
The one-gram case: every offset of Block's gram is itself a candidate start (off - D). Same negative-start rejection as distance_check/4.