query

package
v2.0.0-alpha.16 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TypeNull     = Type(anyenc.TypeNull)
	TypeNumber   = Type(anyenc.TypeNumber)
	TypeString   = Type(anyenc.TypeString)
	TypeFalse    = Type(anyenc.TypeFalse)
	TypeTrue     = Type(anyenc.TypeTrue)
	TypeArray    = Type(anyenc.TypeArray)
	TypeObject   = Type(anyenc.TypeObject)
	TypeObjectID = Type(anyenc.TypeObjectID)
)

Variables

This section is empty.

Functions

func GuaranteesPresence

func GuaranteesPresence(f Filter, fieldName string) bool

GuaranteesPresence reports whether every document matching f must carry a present, non-null value at fieldName. It is true only when some top-level conjunct constrains fieldName with a predicate that rejects BOTH a missing field (a nil value) and an explicit null — exactly the two cases a sparse index omits (see index.writeValues: it drops a key when any indexed field is nil or TypeNull).

The planner uses this to decide whether a SPARSE index can represent the whole matching set: a sparse index that omits some matching document would silently drop rows if seeked. Probing the field's own sub-filter with Ok keeps this in lockstep with match semantics, so it is exact rather than a rule-of-thumb — e.g. {$exists:true} yields false here because an explicit-null document matches $exists:true yet is absent from the sparse index. An OR, a $exists:false, a $ne, an equality-to-null, an $in containing null, or no predicate on the field at all all yield false, keeping that sparse index out of consideration (the planner then falls back to a complete index or scan).

func IsTextScoreSort

func IsTextScoreSort(s Sort) bool

IsTextScoreSort reports whether s requests relevance ordering (directly or as the sole element of a Sorts list).

Types

type All

type All struct{}

func (All) IndexBounds

func (a All) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (All) Ok

func (a All) Ok(_ *anyenc.Value, buf *syncpool.DocBuffer) bool

func (All) String

func (a All) String() string

type And

type And []Filter

func (And) IndexBounds

func (e And) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

IndexBounds returns a SOUND OVER-APPROXIMATION of the index bounds for this conjunction: the bounds of the first conjunct that constrains fieldName. The result must be a SUPERSET of the matching set so the index seek (and Iter) never miss a doc.

Intersecting conjunct bounds (the original I-04 fix) is UNSOUND for ARRAY/multi-key fields: array filter semantics match each conjunct against the whole array independently, so a doc matches {$gte:2,$lte:3} when one element is >=2 and a DIFFERENT element is <=3 — it need not have any element in [2,3]. Narrowing the seek to the intersection drops such docs from both Count and Iter (and a FilterIter cannot re-add what the seek skipped). The over-approximation here is correct for scalar AND array fields because every matching doc has an element satisfying the first conjunct, hence in its bounds; a FilterIter re-checks the full conjunction.

The CountOnly fast path skips that FilterIter, so it would over-count when these over-approx bounds are a strict superset of the matches. It is gated separately: indexCoversFilter rejects a covered field carrying more than one predicate, so the fast path is only taken when bounds exactly equal the matches (a single In/Eq/range per field). See docs/known-issues.md (I-04).

func (And) Ok

func (e And) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (And) String

func (e And) String() string

type Bound

type Bound struct {
	Start, End anyenc.Tuple

	StartInclude bool
	EndInclude   bool
	// contains filtered or unexported fields
}

func (Bound) String

func (b Bound) String() string

type Bounds

type Bounds []Bound

func (Bounds) Append

func (bs Bounds) Append(b Bound) Bounds

func (Bounds) Contains

func (bs Bounds) Contains(val []byte) bool

Contains reports whether val lies within any range in bs. val is a raw anyenc-encoded tuple component (e.g. the field-value prefix of an index key, with docId suffix stripped).

func (Bounds) Len

func (bs Bounds) Len() int

func (Bounds) Less

func (bs Bounds) Less(i, j int) bool

func (Bounds) SortAndMerge

func (bs Bounds) SortAndMerge() Bounds

SortAndMerge sorts bounds by Start key and merges overlapping/adjacent entries in a single O(N log N) pass. Use after batch-appending multiple bounds.

func (Bounds) String

func (bs Bounds) String() string

func (Bounds) Swap

func (bs Bounds) Swap(i, j int)

type Comp

type Comp struct {
	EqValue []byte
	CompOp  CompOp
	// contains filtered or unexported fields
}

func NewComp

func NewComp(op CompOp, value any) *Comp

func NewCompValue

func NewCompValue(op CompOp, value *anyenc.Value) *Comp

func (*Comp) IndexBounds

func (e *Comp) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (*Comp) Ok

func (e *Comp) Ok(v *anyenc.Value, docBuf *syncpool.DocBuffer) bool

func (*Comp) String

func (e *Comp) String() string

type CompOp

type CompOp uint8
const (
	CompOpEq CompOp = iota
	CompOpGt
	CompOpGte
	CompOpLt
	CompOpLte
	CompOpNe
)

type Exists

type Exists struct{}

func (Exists) IndexBounds

func (e Exists) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (Exists) Ok

func (e Exists) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Exists) String

func (e Exists) String() string

type Filter

type Filter interface {
	// Ok evaluates whether the given value satisfies the filter condition.
	// docBuf is optional and can be nil, it's used to reuse memory between
	// calls: with a warm per-query DocBuffer, Ok is alloc-free
	// (TestFilterOkAllocFree).
	Ok(v *anyenc.Value, docBuf *syncpool.DocBuffer) bool

	// IndexBounds appends bounds to the bs for the given field if it is applicable
	IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

	fmt.Stringer
}

Filter is built once (ParseCondition or a constructor) and is immutable afterwards: it may be shared by any number of queries running concurrently. Ok and IndexBounds never mutate filter state and need no synchronization; bound bytes returned by IndexBounds that alias filter memory are clipped to cap == len so downstream appends reallocate instead of writing into the shared filter. Pinned by TestFilterConcurrentReuse and TestIndexBounds_FilterOwnedBytesAreCapped; see docs/query-filter-contract.md.

func MustParseCondition

func MustParseCondition(cond any) Filter

func ParseCondition

func ParseCondition(cond any) (Filter, error)

type In

type In struct {
	// Values is the membership set, keyed by anyenc-marshaled value. A
	// built filter is immutable: once handed to a query it may be used by
	// many queries concurrently, so Values must not be mutated (IndexBounds
	// and Ok read it and the pre-sorted view without synchronization).
	// Build In via NewInValue.
	Values map[string]struct{}
	// contains filtered or unexported fields
}

func NewInValue

func NewInValue(values ...*anyenc.Value) In

func (In) IndexBounds

func (e In) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (In) Ok

func (e In) Ok(v *anyenc.Value, docBuf *syncpool.DocBuffer) bool

func (In) String

func (e In) String() string

type Key

type Key struct {
	Path []string
	Filter
}

func (Key) IndexBounds

func (e Key) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (Key) Ok

func (e Key) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Key) String

func (e Key) String() string

type Modifier

type Modifier interface {
	Modify(a *anyenc.Arena, v *anyenc.Value) (result *anyenc.Value, modified bool, err error)
}

func MustParseModifier

func MustParseModifier(modifier any) Modifier

func ParseModifier

func ParseModifier(modifier any) (Modifier, error)

type ModifierChain

type ModifierChain []Modifier

func (ModifierChain) Modify

func (mRoot ModifierChain) Modify(a *anyenc.Arena, v *anyenc.Value) (result *anyenc.Value, modified bool, err error)

type ModifyFunc

type ModifyFunc func(a *anyenc.Arena, v *anyenc.Value) (result *anyenc.Value, modified bool, err error)

func (ModifyFunc) Modify

func (m ModifyFunc) Modify(a *anyenc.Arena, v *anyenc.Value) (result *anyenc.Value, modified bool, err error)

type Nor

type Nor []Filter

func (Nor) IndexBounds

func (e Nor) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (Nor) Ok

func (e Nor) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Nor) String

func (e Nor) String() string

type Not

type Not struct {
	Filter
}

func (Not) IndexBounds

func (e Not) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (Not) Ok

func (e Not) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Not) String

func (e Not) String() string

type Operator

type Operator uint8

type Or

type Or []Filter

func (Or) IndexBounds

func (e Or) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (Or) Ok

func (e Or) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Or) String

func (e Or) String() string

type Regexp

type Regexp struct {
	Regexp *regexp.Regexp
}

func (Regexp) IndexBounds

func (r Regexp) IndexBounds(_ string, bs Bounds) (bounds Bounds)

func (Regexp) Ok

func (r Regexp) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Regexp) String

func (r Regexp) String() string

type Size

type Size struct {
	Size int64
}

func (Size) IndexBounds

func (s Size) IndexBounds(_ string, bs Bounds) (bounds Bounds)

func (Size) Ok

func (s Size) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Size) String

func (s Size) String() string

type Sort

type Sort interface {
	Fields() []SortField
	AppendKey(k anyenc.Tuple, v *anyenc.Value) anyenc.Tuple
}

func MustParseSort

func MustParseSort(sorts ...any) Sort

func ParseSort

func ParseSort(sorts ...any) (Sort, error)

type SortField

type SortField struct {
	Field   string
	Path    []string
	Reverse bool
}

func (*SortField) AppendKey

func (s *SortField) AppendKey(tuple anyenc.Tuple, v *anyenc.Value) anyenc.Tuple

func (*SortField) Fields

func (s *SortField) Fields() []SortField

type Sorts

type Sorts []Sort

func (Sorts) AppendKey

func (ss Sorts) AppendKey(k anyenc.Tuple, v *anyenc.Value) anyenc.Tuple

func (Sorts) Fields

func (ss Sorts) Fields() []SortField

type Text

type Text struct {
	// Search is the raw $search string, preserved verbatim for String() and as
	// the fallback source when Clauses is nil (a directly-constructed Text).
	Search string
	// DefaultAnd is set by {"$defaultOperator":"and"}: bare (should) terms then
	// become required (AND) rather than the default OR.
	DefaultAnd bool
	// Clauses are the parsed clauses of the whole $text predicate: the should
	// clauses from $search (phrases, prefix*, plain terms) plus the required and
	// excluded clauses from the $require / $exclude sub-fields. Populated by
	// ParseCondition; a Text built directly with only Search set has nil Clauses
	// and the executor re-parses Search on demand (yielding should clauses only).
	Clauses []TextClause
}

Text is the {"$text":{"$search":"..."}} full-text predicate. Matching and ranking are performed by the full-text index (the query is driven by an FTS scan), so as a residual predicate Ok always passes: any document the FTS scan yields has already matched. It contributes no index bounds.

CAUTION: this makes Text meaningful only inside an FTS-driven query. Used standalone — calling Ok directly to post-filter documents, as subscription-style consumers of this package do — a $text condition silently matches EVERY document; Ok never evaluates the search text. Placement rules ($text only at the top level or inside $and, at most one per query) are also enforced by the executor, not here. See docs/fts/DESIGN.md.

func (Text) IndexBounds

func (t Text) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (Text) Ok

func (t Text) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (Text) ParsedClauses

func (t Text) ParsedClauses() []TextClause

ParsedClauses returns the parsed clauses, parsing Search on demand for a Text that was constructed directly (Clauses nil) rather than via ParseCondition.

func (Text) String

func (t Text) String() string

type TextClause

type TextClause struct {
	// Raw is the unanalyzed clause text: a single word, or the inner text of a
	// "quoted phrase".
	Raw string
	// Phrase marks a "..." clause: Raw analyzes to an ordered term list matched
	// by positional adjacency.
	Phrase bool
	// Prefix marks a trailing-* clause (foo*): Raw's single analyzed term is
	// expanded against the vocabulary. Mutually exclusive with Phrase.
	Prefix bool
	// Op is the clause's boolean role.
	Op TextOp
}

TextClause is one parsed unit of a $text $search string: a single term, a quoted phrase, or a prefix term, together with its boolean role. The raw text is NOT analyzed here — the query package stays free of the fts analyzer; the FTS executor analyzes each clause with the index's own pipeline.

func ParseTextSearch

func ParseTextSearch(s string) []TextClause

ParseTextSearch splits a $text $search string into clauses. It is a purely syntactic scan — no analysis/tokenization happens here (that is the FTS executor's job, using the index's analyzer). Every clause it returns is a should (OR) clause; required/excluded clauses come from the typed $require / $exclude sub-fields instead (see parseText), not from inline string signs.

  • "double quoted" → a phrase clause (positional adjacency).
  • word* → a prefix clause (vocabulary expansion).
  • word → a plain term clause.

Deliberately there is NO inline +/- boolean syntax. Parsing boolean intent out of a raw human search string is a footgun for an embedded library whose common use is "forward the end-user's search box straight into $search": a user typing "-9" (meaning −9°C) or "+1" (a vote) would silently get an exclusion/require. The same characters are harmless here — they are punctuation the analyzer drops — so "-9" is just the term "9". Boolean require/exclude lives in the structured $require / $exclude arrays, which are unambiguous and run through the same analyzer. An app that wants single-box power-user syntax can parse it itself and populate those fields. A trailing * is still honoured on bare words (prefix expansion has negligible false-positive rate in natural text); it is left literal inside a phrase, where positional expansion would be combinatorial.

type TextOp

type TextOp uint8

TextOp classifies a $text clause's boolean role within the query.

const (
	// TextShould is a default clause: OR'd with the other should-clauses, unless
	// the query sets DefaultAnd, in which case it is required.
	TextShould TextOp = iota
	// TextMust is a +term: always required (AND), regardless of DefaultAnd.
	TextMust
	// TextMustNot is a -term: documents containing it are excluded.
	TextMustNot
)

type TextScoreSort

type TextScoreSort struct {
	Field string
}

TextScoreSort marks a request to order full-text results by descending relevance ({"<field>":{"$meta":"textScore"}}). It carries no document field — the full-text scan already yields documents in score order — so AppendKey and Fields are inert; the query layer recognises the type and keeps scan order.

func (TextScoreSort) AppendKey

func (TextScoreSort) AppendKey(k anyenc.Tuple, _ *anyenc.Value) anyenc.Tuple

func (TextScoreSort) Fields

func (TextScoreSort) Fields() []SortField

func (TextScoreSort) String

func (TextScoreSort) String() string

type Type

type Type anyenc.Type

func (Type) String

func (t Type) String() string

type TypeFilter

type TypeFilter struct {
	Type anyenc.Type
}

func (TypeFilter) IndexBounds

func (e TypeFilter) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)

func (TypeFilter) Ok

func (e TypeFilter) Ok(v *anyenc.Value, buf *syncpool.DocBuffer) bool

func (TypeFilter) String

func (e TypeFilter) String() string

Jump to

Keyboard shortcuts

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