mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-09-13 14:18:38 -04:00
Keyword and path fields always index their case-preserved base and, when CaseInsensitive is set, an additional <field>_lowercase sibling used only for matching. The KQL lowering marks a restriction case-insensitive; each backend searches the sibling and lowercases the query value the same way the sibling is precomputed at index time (Go strings.ToLower on both sides, so non-ASCII stays consistent). Search always returns the case-preserved base, so the sibling never has to be read back. In bleve it is indexed but not stored, kept out of _all, and without doc values. In OpenSearch it deliberately stays in _source: excluding it would make every update-by-query script rebuild all siblings from the document via painless toLowerCase, which lowercases differently than Go and would drift from the query side. Keeping it in _source avoids that, and a lowercased copy of a name or path is negligible disk in a cluster. The OpenSearch move script keeps the base and its sibling in sync by swapping the moved prefix in Path_lowercase and setting Name_lowercase from Go-lowercased params, so case-insensitive search still finds a file after it moves (previously the sibling went stale). bleve re-indexes the whole document on move/delete/restore, so its siblings stay fresh for free. This also repairs OpenSearch path search (the query value was no longer folded to lowercase, so path:<Foo> returned nothing) and makes bleve path queries match a folder and its descendants like OpenSearch's path_hierarchy. The Path base stays case-preserved so the move/delete descendant update (an exact TermQuery on Path) matches mixed-case folders.
120 lines
2.2 KiB
Go
120 lines
2.2 KiB
Go
// Package ast provides available ast nodes.
|
|
package ast
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
// Node represents abstract syntax tree node
|
|
type Node interface {
|
|
Location() *Location
|
|
}
|
|
|
|
// Position represents a specific location in the source
|
|
type Position struct {
|
|
Line int
|
|
Column int
|
|
}
|
|
|
|
// Location represents the location of a node in the AST
|
|
type Location struct {
|
|
Start Position `json:"start"`
|
|
End Position `json:"end"`
|
|
Source *string `json:"source,omitempty"`
|
|
}
|
|
|
|
// Base contains shared node attributes
|
|
// each node should inherit from this
|
|
type Base struct {
|
|
Loc *Location
|
|
}
|
|
|
|
// Location is the source location of the Node
|
|
func (b *Base) Location() *Location { return b.Loc }
|
|
|
|
// Ast represents the query - node structure as abstract syntax tree
|
|
type Ast struct {
|
|
*Base
|
|
Nodes []Node `json:"body"`
|
|
}
|
|
|
|
// StringNode represents a string value
|
|
type StringNode struct {
|
|
*Base
|
|
Key string
|
|
Value string
|
|
Exact bool
|
|
// CaseInsensitive marks a case-insensitive restriction; set by the search
|
|
// lowering pass, a backend routes it to the field's lowercased form.
|
|
CaseInsensitive bool
|
|
}
|
|
|
|
// BooleanNode represents a bool value
|
|
type BooleanNode struct {
|
|
*Base
|
|
Key string
|
|
Value bool
|
|
}
|
|
|
|
// DateTimeNode represents a time.Time value
|
|
type DateTimeNode struct {
|
|
*Base
|
|
Key string
|
|
Operator *OperatorNode
|
|
Value time.Time
|
|
}
|
|
|
|
// NumberNode represents a numeric value
|
|
type NumberNode struct {
|
|
*Base
|
|
Key string
|
|
Operator *OperatorNode
|
|
Value float64
|
|
}
|
|
|
|
// OperatorNode represents an operator value like
|
|
// AND, OR, NOT, =, <= ... and so on
|
|
type OperatorNode struct {
|
|
*Base
|
|
Value string
|
|
}
|
|
|
|
// GroupNode represents a collection of many grouped nodes
|
|
type GroupNode struct {
|
|
*Base
|
|
Key string
|
|
Nodes []Node
|
|
}
|
|
|
|
// NodeKey tries to return the node key
|
|
func NodeKey(n Node) string {
|
|
switch node := n.(type) {
|
|
case *StringNode:
|
|
return node.Key
|
|
case *DateTimeNode:
|
|
return node.Key
|
|
case *BooleanNode:
|
|
return node.Key
|
|
case *GroupNode:
|
|
return node.Key
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
// NodeValue tries to return the node key
|
|
func NodeValue(n Node) any {
|
|
switch node := n.(type) {
|
|
case *StringNode:
|
|
return node.Value
|
|
case *DateTimeNode:
|
|
return node.Value
|
|
case *BooleanNode:
|
|
return node.Value
|
|
case *GroupNode:
|
|
return node.Nodes
|
|
default:
|
|
return ""
|
|
}
|
|
}
|