bloom

package
v0.40.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 22, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package bloom is a token bloom filter for full-text pruning: a compact, approximate set of the terms present in a column block (e.g. every token across a log part's bodies). A query token that tests **absent** is definitely not in the block, so the reader skips the whole block; a token that tests present may be a false positive, so the engine re-checks the exact predicate per row. The filter never reports a false negative — a token that was [Filter.Add]ed always [Filter.Test]s present — which is what makes block-skipping safe.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Bits added in v0.33.0

func Bits(n int, p float64) uint64

Bits returns the bit count New would allocate for n items at rate p, so a caller can price a filter (its bytes are Bits/8 plus a small header) before deciding how carefully to count n.

func CountTokens added in v0.33.0

func CountTokens(s []byte) int

CountTokens returns how many tokens s yields, without producing any. Sizing a filter from it and then filling the filter from a Scanner over the same input costs no token materialization.

func Hashes added in v0.33.0

func Hashes(item []byte) (h1, h2 uint64)

Hashes returns the pair of hashes identifying item, for use with Filter.AddHashes. It is the hash Filter.Add and Filter.Test derive their probes from, so a caller that caches these reproduces exactly the same filter.

func SafeTokens added in v0.29.0

func SafeTokens(dst [][]byte, lit []byte, leftPinned, rightPinned bool) [][]byte

SafeTokens appends to dst the tokens that are provably present in *any* value a `contains lit` predicate matches, and returns the extended slice. It is the query-side companion to Tokenize: an embedder that lowers a substring/regexp filter to a required literal feeds that literal here, sets the result as a fetch condition's token hint, and the per-part token bloom then prunes any part whose bloom lacks one of these tokens — without ever pruning a part that holds a real match.

The safety rule. The bloom holds whole tokens (maximal alphanumeric runs). A value containing lit as a substring may glue extra alphanumerics onto lit's first/last token — "GET" occurs inside "xGETy", whose token is "xgety", not "get" — so lit's edge tokens are NOT guaranteed to be whole tokens of the value, and testing them would wrongly prune a match. SafeTokens therefore drops the leading and trailing partial token (the run of alphanumerics touching each edge) before tokenizing, keeping only interior tokens that a separator bounds on both sides within lit. Every returned token T satisfies: a value that contains lit contains T as a whole token, i.e. T ∈ Tokenize(value). The extraction under-approximates by design — a single-word literal yields no tokens (no pruning, a full scan, still correct) rather than an unsafe one.

leftPinned/rightPinned tell SafeTokens an edge cannot be extended, so its edge token is safe to keep: set them when an anchor (^, $), a word boundary (\b), or an exact-equality match guarantees the value does not glue an alphanumeric onto that side of lit. With both pinned lit is matched exactly, so every token of lit is safe.

func Tokenize

func Tokenize(dst [][]byte, s []byte) [][]byte

Tokenize splits s into lowercased tokens — maximal runs of ASCII letters/digits — appending each to dst and returning the extended slice. Non-alphanumeric bytes are separators. Each token is a freshly allocated, lowercased copy (it does not alias s). It is the tokenization used both to fill a body bloom at flush and to derive a query's required tokens, so the two agree.

It allocates a token at a time, which suits the query side (a handful of tokens per predicate). A flush tokenizing whole columns should use Scanner instead, which yields the same tokens without allocating.

Types

type Filter

type Filter struct {
	// contains filtered or unexported fields
}

Filter is a bit-array bloom filter with k hash probes derived from one 128-bit hash by double-hashing (Kirsch–Mitzenmacher). The zero value is not usable; build one with New.

func Decode

func Decode(src []byte) (*Filter, int, error)

Decode parses a filter encoded by Filter.Encode, returning it and the number of bytes consumed. It is fully bounds-checked and verifies the trailing CRC.

func New

func New(n int, p float64) *Filter

New returns a filter sized for n expected items at false-positive rate p (0 < p < 1), using the standard m = -n·ln p / (ln2)² and k = (m/n)·ln2, with m rounded up to a multiple of 64 and both m and k clamped to at least their minimums.

func (*Filter) Add

func (f *Filter) Add(item []byte)

Add records item in the filter.

func (*Filter) AddHashes added in v0.33.0

func (f *Filter) AddHashes(h1, h2 uint64)

AddHashes records the item whose Hashes are h1, h2 — the same bits Filter.Add would set, for a caller that already hashed the item (e.g. a builder that hashes once and sizes the filter afterwards, rather than hashing the column twice).

func (*Filter) Encode

func (f *Filter) Encode(dst []byte) []byte

Encode appends the filter's self-describing wire form to dst: [version][uvarint k][uvarint m][bits little-endian]…[u32 CRC32C of the preceding bytes].

func (*Filter) Test

func (f *Filter) Test(item []byte) bool

Test reports whether item may be present: true if every probe bit is set (possibly a false positive), false if any is clear (definitely absent — no false negatives).

type Scanner added in v0.33.0

type Scanner struct {
	// contains filtered or unexported fields
}

Scanner walks the lowercased tokens of a byte slice — the same tokens Tokenize produces — without allocating per token. A token that is already lowercase aliases the input; one holding uppercase is folded into the scanner's reusable buffer. Either way the returned slice is valid only until the next call to Scanner.Next or Scanner.Reset, so a caller that retains a token must copy it.

The zero value is ready to use. Reuse one scanner across values so the fold buffer is kept. Not safe for concurrent use.

func (*Scanner) Next added in v0.33.0

func (sc *Scanner) Next() ([]byte, bool)

Next returns the next token and whether one was found.

func (*Scanner) Reset added in v0.33.0

func (sc *Scanner) Reset(s []byte)

Reset points the scanner at s, rewinding it.

type Sketch added in v0.33.0

type Sketch struct {
	// contains filtered or unexported fields
}

Sketch estimates how many *distinct* items a stream contains, in constant space (HyperLogLog). A bloom filter must be sized by its distinct item count: sizing by the number of occurrences over-allocates by the average repetition factor, which for tokenized log text is one to two orders of magnitude (the same words recur in every row). The zero value is ready to use; Sketch.Reset re-arms it.

func (*Sketch) Add added in v0.33.0

func (s *Sketch) Add(item []byte)

Add records item.

func (*Sketch) AddHash added in v0.33.0

func (s *Sketch) AddHash(h uint64)

AddHash records an item by its hash, for a caller that already hashed it (e.g. through Hashes). Any well-distributed 64-bit hash works, as long as one item always yields one hash.

func (*Sketch) Estimate added in v0.33.0

func (s *Sketch) Estimate() int

Estimate returns the approximate number of distinct items added, using the standard HyperLogLog estimator with linear counting on the sparse (small-cardinality) range.

func (*Sketch) Reset added in v0.33.0

func (s *Sketch) Reset()

Reset clears the sketch for a fresh count.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL