barrel_ngram_postings_positional (barrel_ngram v0.9.0)

View Source

Positional (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

cursor/0

-opaque cursor()

entry/0

-type entry() :: {ordinal(), [offset()]}.

offset/0

-type offset() :: non_neg_integer().

ordinal/0

-type ordinal() :: barrel_ngram_postings:ordinal().

Functions

cursor(Bin)

-spec cursor(binary()) -> cursor().

A cursor positioned before the first entry of a positional block.

decode(Bin)

-spec decode(binary()) -> [entry()].

Decode a positional block back to [{Ordinal, [Offset]}], ascending by ordinal, each offset list ascending.

distance_check(BlockA, D1, BlockB, D2)

-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(Entries)

-spec encode([entry()]) -> binary().

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.

next(Cursor)

-spec next(cursor()) -> {ordinal(), [offset()], cursor()} | done.

The next {Ordinal, Offsets, Cursor}, or done.

single_gram_candidates(Block, D)

-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.