Documentation
¶
Index ¶
- Constants
- func GuaranteesPresence(f Filter, fieldName string) bool
- func IsTextScoreSort(s Sort) bool
- type All
- type And
- type Bound
- type Bounds
- type Comp
- type CompOp
- type Exists
- type Filter
- type In
- type Key
- type Modifier
- type ModifierChain
- type ModifyFunc
- type Nor
- type Not
- type Operator
- type Or
- type Regexp
- type Size
- type Sort
- type SortField
- type Sorts
- type Text
- type TextClause
- type TextOp
- type TextScoreSort
- type Type
- type TypeFilter
Constants ¶
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 ¶
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 ¶
IsTextScoreSort reports whether s requests relevance ordering (directly or as the sole element of a Sorts list).
Types ¶
type And ¶
type And []Filter
func (And) IndexBounds ¶
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).
type Bound ¶
type Bounds ¶
type Bounds []Bound
func (Bounds) Contains ¶
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) SortAndMerge ¶
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.
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 ParseCondition ¶
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 ¶
type Modifier ¶
type Modifier interface {
Modify(a *anyenc.Arena, v *anyenc.Value) (result *anyenc.Value, modified bool, err error)
}
func MustParseModifier ¶
func ParseModifier ¶
type ModifierChain ¶
type ModifierChain []Modifier
type ModifyFunc ¶
type Sort ¶
type Sort interface {
Fields() []SortField
AppendKey(k anyenc.Tuple, v *anyenc.Value) anyenc.Tuple
}
func MustParseSort ¶
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) 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.
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) Fields ¶
func (TextScoreSort) Fields() []SortField
func (TextScoreSort) String ¶
func (TextScoreSort) String() string
type TypeFilter ¶
func (TypeFilter) IndexBounds ¶
func (e TypeFilter) IndexBounds(fieldName string, bs Bounds) (bounds Bounds)
func (TypeFilter) String ¶
func (e TypeFilter) String() string