Files
opencloud/services/search/pkg/mapping/validate.go
Dominik Schmidt ac86d9b907 refactor: reflection-based search mapping
Build the bleve and OpenSearch index mappings from the Go struct via
reflection (json tags + per-field overrides) instead of hand-rolled
mappings and hit deserializers. New mapping package: BleveBuildMapping,
OpenSearchBuildMapping, Deserialize[T], PrepareForIndex; field decoding is
fail-soft. Mtime is typed as a date so mtime ranges are chronological on
both backends. Route CS3 facet parsing through mapping.DeserializeStringMap.

The any-valued (bleve hit) and string-valued (CS3 metadata) deserializers
share one generic fillStruct walker with a per-value setLeaf callback.
2026-07-02 16:04:46 +02:00

50 lines
1.2 KiB
Go

package mapping
import (
"fmt"
"reflect"
"sort"
"strings"
)
// Validate returns an error if any override key does not match a known field
// name in t. Top-level fields are identified by their json-tag name; nested
// named struct fields are reachable as "parent.child". Embedded (anonymous)
// structs are flattened, so their fields sit at the parent level (as with
// encoding/json).
func Validate(t reflect.Type, overrides map[string]FieldOpts) error {
if len(overrides) == 0 {
return nil
}
names := collectNames(t, "")
var unknown []string
for k := range overrides {
if _, ok := names[k]; !ok {
unknown = append(unknown, k)
}
}
if len(unknown) == 0 {
return nil
}
sort.Strings(unknown)
return fmt.Errorf("mapping: unknown override keys: %s", strings.Join(unknown, ", "))
}
func collectNames(t reflect.Type, prefix string) map[string]struct{} {
out := map[string]struct{}{}
_ = walkFields(t, func(fi fieldInfo) error {
key := fi.Name
if prefix != "" {
key = prefix + "." + fi.Name
}
out[key] = struct{}{}
if sub := structType(fi.GoField.Type); sub != nil {
for k := range collectNames(sub, key) {
out[k] = struct{}{}
}
}
return nil
})
return out
}