full filter interpretation
This commit is contained in:
+43
-14
@@ -165,7 +165,7 @@ func FiltersFromFlatMap(flatMap map[string]interface{}, target interface{}) *Fil
|
|||||||
And: make(map[string][]Filter),
|
And: make(map[string][]Filter),
|
||||||
Or: make(map[string][]Filter),
|
Or: make(map[string][]Filter),
|
||||||
}
|
}
|
||||||
paths := jsonToBsonPaths(reflect.TypeOf(target), "")
|
paths := jsonToBsonPaths(reflect.TypeOf(target), "", "")
|
||||||
resolve := func(jsonKey string) string {
|
resolve := func(jsonKey string) string {
|
||||||
if p, ok := paths[jsonKey]; ok {
|
if p, ok := paths[jsonKey]; ok {
|
||||||
return p
|
return p
|
||||||
@@ -215,11 +215,22 @@ func FiltersFromFlatMap(flatMap map[string]interface{}, target interface{}) *Fil
|
|||||||
//
|
//
|
||||||
// Anonymous embedded fields without any tag follow the BSON convention of this
|
// Anonymous embedded fields without any tag follow the BSON convention of this
|
||||||
// codebase: they are stored as a nested sub-document whose key is the lowercased
|
// codebase: they are stored as a nested sub-document whose key is the lowercased
|
||||||
// struct type name (e.g. utils.AbstractObject → "abstractobject").
|
// struct type name (e.g. utils.AbstractObject → "abstractobject"). Their JSON
|
||||||
func jsonToBsonPaths(t reflect.Type, prefix string) map[string]string {
|
// fields are promoted (flat), so bsonPrefix advances but jsonPrefix does not.
|
||||||
|
//
|
||||||
|
// For fields inside slices or maps, both the leaf json name and the full dotted
|
||||||
|
// json path (e.g. "instances.access_protocol") are registered as keys so callers
|
||||||
|
// can use either form unambiguously.
|
||||||
|
func jsonToBsonPaths(t reflect.Type, bsonPrefix string, jsonPrefix string) map[string]string {
|
||||||
for t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice {
|
for t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice {
|
||||||
t = t.Elem()
|
t = t.Elem()
|
||||||
}
|
}
|
||||||
|
if t.Kind() == reflect.Map {
|
||||||
|
t = t.Elem()
|
||||||
|
for t.Kind() == reflect.Ptr {
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
result := make(map[string]string)
|
result := make(map[string]string)
|
||||||
if t.Kind() != reflect.Struct {
|
if t.Kind() != reflect.Struct {
|
||||||
return result
|
return result
|
||||||
@@ -233,20 +244,21 @@ func jsonToBsonPaths(t reflect.Type, prefix string) map[string]string {
|
|||||||
bsonName := strings.Split(bsonTag, ",")[0]
|
bsonName := strings.Split(bsonTag, ",")[0]
|
||||||
|
|
||||||
// Anonymous embedded struct with no tags: use lowercase type name as BSON prefix.
|
// Anonymous embedded struct with no tags: use lowercase type name as BSON prefix.
|
||||||
|
// JSON fields are promoted so jsonPrefix stays the same.
|
||||||
if field.Anonymous && jsonName == "" && bsonName == "" {
|
if field.Anonymous && jsonName == "" && bsonName == "" {
|
||||||
ft := field.Type
|
ft := field.Type
|
||||||
for ft.Kind() == reflect.Ptr {
|
for ft.Kind() == reflect.Ptr {
|
||||||
ft = ft.Elem()
|
ft = ft.Elem()
|
||||||
}
|
}
|
||||||
if ft.Kind() == reflect.Struct {
|
if ft.Kind() == reflect.Struct {
|
||||||
embedPrefix := strings.ToLower(ft.Name())
|
embedBsonPrefix := strings.ToLower(ft.Name())
|
||||||
re := regexp.MustCompile(`\[[^\]]*\]`)
|
re := regexp.MustCompile(`\[[^\]]*\]`)
|
||||||
embedPrefix = re.ReplaceAllString(embedPrefix, "")
|
embedBsonPrefix = re.ReplaceAllString(embedBsonPrefix, "")
|
||||||
embedPrefix = strings.ReplaceAll(embedPrefix, "*", "")
|
embedBsonPrefix = strings.ReplaceAll(embedBsonPrefix, "*", "")
|
||||||
if prefix != "" {
|
if bsonPrefix != "" {
|
||||||
embedPrefix = prefix + "." + embedPrefix
|
embedBsonPrefix = bsonPrefix + "." + embedBsonPrefix
|
||||||
}
|
}
|
||||||
for k, v := range jsonToBsonPaths(ft, embedPrefix) {
|
for k, v := range jsonToBsonPaths(ft, embedBsonPrefix, jsonPrefix) {
|
||||||
if _, exists := result[k]; !exists {
|
if _, exists := result[k]; !exists {
|
||||||
result[k] = v
|
result[k] = v
|
||||||
}
|
}
|
||||||
@@ -262,19 +274,36 @@ func jsonToBsonPaths(t reflect.Type, prefix string) map[string]string {
|
|||||||
bsonName = jsonName
|
bsonName = jsonName
|
||||||
}
|
}
|
||||||
|
|
||||||
fullPath := bsonName
|
fullBsonPath := bsonName
|
||||||
if prefix != "" {
|
if bsonPrefix != "" {
|
||||||
fullPath = prefix + "." + bsonName
|
fullBsonPath = bsonPrefix + "." + bsonName
|
||||||
|
}
|
||||||
|
fullJsonPath := jsonName
|
||||||
|
if jsonPrefix != "" {
|
||||||
|
fullJsonPath = jsonPrefix + "." + jsonName
|
||||||
}
|
}
|
||||||
|
|
||||||
result[jsonName] = fullPath
|
result[jsonName] = fullBsonPath
|
||||||
|
// Also register the full dotted JSON path so callers can use
|
||||||
|
// "instances.access_protocol" instead of just "access_protocol".
|
||||||
|
if fullJsonPath != jsonName {
|
||||||
|
if _, exists := result[fullJsonPath]; !exists {
|
||||||
|
result[fullJsonPath] = fullBsonPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ft := field.Type
|
ft := field.Type
|
||||||
for ft.Kind() == reflect.Ptr || ft.Kind() == reflect.Slice {
|
for ft.Kind() == reflect.Ptr || ft.Kind() == reflect.Slice {
|
||||||
ft = ft.Elem()
|
ft = ft.Elem()
|
||||||
}
|
}
|
||||||
|
if ft.Kind() == reflect.Map {
|
||||||
|
ft = ft.Elem()
|
||||||
|
for ft.Kind() == reflect.Ptr {
|
||||||
|
ft = ft.Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
if ft.Kind() == reflect.Struct {
|
if ft.Kind() == reflect.Struct {
|
||||||
for k, v := range jsonToBsonPaths(ft, fullPath) {
|
for k, v := range jsonToBsonPaths(ft, fullBsonPath, fullJsonPath) {
|
||||||
if _, exists := result[k]; !exists {
|
if _, exists := result[k]; !exists {
|
||||||
result[k] = v
|
result[k] = v
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user