- fix references in nested structs not being registered properly
- rework struct tag parsing
- remove debug logs
- fix bug where an unrelated field with the same prefix as another population path is erroneously marked as populated
This commit is contained in:
☙◦ The Tablet ❀ GamerGirlandCo ◦❧ 2025-04-10 00:32:59 -04:00
parent c85efdc49f
commit 510a126f4b
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C
3 changed files with 71 additions and 69 deletions

View File

@ -9,7 +9,6 @@ import (
"go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/mongo/options"
"reflect" "reflect"
"strings"
"time" "time"
) )
@ -80,11 +79,9 @@ func serializeIDs(input interface{}, isJson bool, populated map[string]bool, par
} }
var ip bool var ip bool
for k1, v1 := range populated { for k1, v1 := range populated {
if k1 == descent || k1 == parent { if k1 == descent {
ip = v1 ip = v1
break break
} else if strings.HasPrefix(k1, descent) {
ip = v1
} }
} }
if terr == nil { if terr == nil {

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"github.com/fatih/structtag" "github.com/fatih/structtag"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo"
@ -186,8 +185,6 @@ func populate(r Reference, rcoll string, rawDoc interface{}, d string, src inter
} }
if hatred.CanSet() { if hatred.CanSet() {
if reflect.ValueOf(t).Kind() == reflect.Pointer { if reflect.ValueOf(t).Kind() == reflect.Pointer {
fmt.Println(reflect.ValueOf(t).Elem().Type().String())
fmt.Println(rv.Type().String())
if hatred.Kind() == reflect.Pointer { if hatred.Kind() == reflect.Pointer {
hatred.Set(reflect.ValueOf(t)) hatred.Set(reflect.ValueOf(t))
} else { } else {
@ -292,6 +289,9 @@ func readFields(field string, m *Model) (Reference, string) {
} }
} }
} }
} else if ok {
r = m.references[field]
break
} }
if keptKey != "" { if keptKey != "" {
break break

View File

@ -6,6 +6,7 @@ import (
"log" "log"
"reflect" "reflect"
"sync" "sync"
"time"
"github.com/fatih/structtag" "github.com/fatih/structtag"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
@ -111,48 +112,38 @@ func makeRef(idx int, modelName string, fieldName string, ht reflect.Type) Refer
panic("model name was empty") panic("model name was empty")
} }
func parseTags(t reflect.Type, v reflect.Value, lastParsed string, eqCount int) (map[string][]InternalIndex, map[string]Reference, map[string]gridFSReference, string) { type parseResult []string
func (p parseResult) includes(str string) bool {
for _, v := range p {
if v == str {
return true
}
}
return false
}
func parseTags(t reflect.Type, v reflect.Value, lastParsed parseResult, depth int) (map[string][]InternalIndex, map[string]Reference, map[string]gridFSReference, string) {
coll := "" coll := ""
refs := make(map[string]Reference) refs := make(map[string]Reference)
idcs := make(map[string][]InternalIndex) idcs := make(map[string][]InternalIndex)
gfsRefs := make(map[string]gridFSReference) gfsRefs := make(map[string]gridFSReference)
if depth >= 4 {
return idcs, refs, gfsRefs, coll
}
for i := 0; i < v.NumField(); i++ { for i := 0; i < v.NumField(); i++ {
sft := t.Field(i) sft := t.Field(i)
ft := sft.Type ft := sft.Type
tags, err := structtag.Parse(string(sft.Tag)) tags, err := structtag.Parse(string(sft.Tag))
panik(err) panik(err)
shouldContinue := true
for {
if !shouldContinue {
break
}
switch ft.Kind() { switch ft.Kind() {
case reflect.Slice: case reflect.Slice:
ft = ft.Elem() ft = ft.Elem()
count := eqCount fallthrough
if lastParsed != ft.String() {
count = 0
} else {
count = count + 1
}
if /*_, ok := tags.Get("ref"); ok != nil && */ count < 3 {
if ft.Kind() == reflect.Struct {
ii2, rr2, gg2, _ := parseTags(ft, reflect.New(ft).Elem(), ft.String(), count)
for k, vv := range ii2 {
idcs[sft.Name+"."+k] = vv
}
for k, vv := range rr2 {
refs[sft.Name+"."+k] = vv
}
for k, vv := range gg2 {
gfsRefs[sft.Name+"."+k] = vv
}
}
}
continue
case reflect.Pointer: case reflect.Pointer:
if ft.Kind() == reflect.Pointer {
ft = ft.Elem() ft = ft.Elem()
}
fallthrough fallthrough
case reflect.Struct: case reflect.Struct:
if ft.ConvertibleTo(reflect.TypeOf(Document{})) { if ft.ConvertibleTo(reflect.TypeOf(Document{})) {
@ -163,8 +154,25 @@ func parseTags(t reflect.Type, v reflect.Value, lastParsed string, eqCount int)
if err == nil { if err == nil {
idcs[sft.Type.Name()] = scanIndex(idxTag.Value()) idcs[sft.Type.Name()] = scanIndex(idxTag.Value())
} }
shouldContinue = false continue
break }
if lastParsed.includes(sft.Name) {
continue
}
blip := lastParsed
blip = append(blip, sft.Name)
if ft.Kind() == reflect.Struct && ft != reflect.TypeFor[time.Time]() {
ii2, rr2, gg2, _ := parseTags(ft, reflect.New(ft).Elem(), blip, depth+1)
for k, vv := range ii2 {
idcs[sft.Name+"."+k] = vv
}
for k, vv := range rr2 {
refs[sft.Name+"."+k] = vv
}
for k, vv := range gg2 {
gfsRefs[sft.Name+"."+k] = vv
}
} }
if refTag, ok := tags.Get("ref"); ok == nil { if refTag, ok := tags.Get("ref"); ok == nil {
sname := sft.Name sname := sft.Name
@ -184,9 +192,6 @@ func parseTags(t reflect.Type, v reflect.Value, lastParsed string, eqCount int)
sname := sft.Name + "@" + gtag.Name sname := sft.Name + "@" + gtag.Name
gfsRefs[sname] = makeGfsRef(gtag, i) gfsRefs[sname] = makeGfsRef(gtag, i)
} }
shouldContinue = false
}
} }
} }
return idcs, refs, gfsRefs, coll return idcs, refs, gfsRefs, coll
@ -304,7 +309,7 @@ func (r TModelRegistry) Model(mdl ...any) {
if idx < 0 { if idx < 0 {
panic("A model must embed the Document struct!") panic("A model must embed the Document struct!")
} }
inds, refs, gfs, coll := parseTags(t, v, "", 0) inds, refs, gfs, coll := parseTags(t, v, make(parseResult, 0), 0)
if coll == "" { if coll == "" {
panic(fmt.Sprintf("a Document needs to be given a collection name! (passed type: %s)", n)) panic(fmt.Sprintf("a Document needs to be given a collection name! (passed type: %s)", n))
} }