From 5585634c837d5936f4175e872bb66ed8c1578b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=99=E2=97=A6=20The=20Tablet=20=E2=9D=80=20GamerGirla?= =?UTF-8?q?ndCo=20=E2=97=A6=E2=9D=A7?= Date: Sun, 6 Apr 2025 22:18:27 -0400 Subject: [PATCH] nvm figured it out lol? --- document.go | 3 ++ document_internals.go | 23 ++++++++++---- model.go | 4 ++- query.go | 70 ++++++++++++++++++++++++++++++++++++------- registry.go | 6 +++- 5 files changed, 89 insertions(+), 17 deletions(-) diff --git a/document.go b/document.go index f188729..197f695 100644 --- a/document.go +++ b/document.go @@ -15,6 +15,7 @@ type Document struct { model *Model `bson:"-"` exists bool `bson:"-"` self any `bson:"-"` + raw any `bson:"-"` populatedFields map[string]bool `bson:"-"` } @@ -68,6 +69,8 @@ type IDocument interface { markPopulated(field string) markDepopulated(field string) newPopulationMap() + getRaw() any + setRaw(raw any) } type SaveOptions struct { diff --git a/document_internals.go b/document_internals.go index 34f5c31..21f9912 100644 --- a/document_internals.go +++ b/document_internals.go @@ -9,6 +9,7 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" "reflect" + "strings" "time" ) @@ -79,9 +80,11 @@ func serializeIDs(input interface{}, isJson bool, populated map[string]bool, par } var ip bool for k1, v1 := range populated { - if k1 == parent { + if k1 == descent || k1 == parent { ip = v1 break + } else if strings.HasPrefix(k1, descent) { + ip = v1 } } if terr == nil { @@ -93,7 +96,9 @@ func serializeIDs(input interface{}, isJson bool, populated map[string]bool, par rarr = append(rarr, getID(fv.Index(j).Interface())) } else { if ip { - ret0[bbson.Name] = serializeIDs(fv.Index(j).Interface(), isJson, populated, descent) + rarr = append(rarr, serializeIDs(fv.Index(j).Interface(), isJson, populated, descent)) + } else { + rarr = append(rarr, getID(fv.Index(j).Interface())) } } } @@ -101,15 +106,15 @@ func serializeIDs(input interface{}, isJson bool, populated map[string]bool, par } else if !ok { panic(fmt.Sprintf("referenced model slice at '%s.%s' does not implement HasID", nameOf(input), ft.Name)) } else { - if reflect.ValueOf(ifc).IsNil() { + if reflect.ValueOf(ifc).IsNil() || reflect.ValueOf(ifc.Id()).IsZero() { ret0[bbson.Name] = nil } else { if !isJson { ret0[bbson.Name] = ifc.Id() } else { - if ip { + if ip && bbson.Name != "-" { ret0[bbson.Name] = serializeIDs(fv.Interface(), isJson, populated, descent) - } else { + } else if bbson.Name != "-" { ret0[bbson.Name] = ifc.Id() } } @@ -313,3 +318,11 @@ func (d *Document) newPopulationMap() { d.populatedFields = make(map[string]bool) } } + +func (d *Document) setRaw(raw any) { + d.raw = raw +} + +func (d *Document) getRaw() any { + return d.raw +} diff --git a/model.go b/model.go index 03d8db2..2166b01 100644 --- a/model.go +++ b/model.go @@ -132,8 +132,9 @@ func (m *Model) Find(query interface{}, opts *options.FindOptionsBuilder) (*Quer qq.reOrganize() err = nil } - for _, doc := range idoc { + for i, doc := range idoc { doc.setModel(*m) + doc.setRaw(rawRes[i]) } } @@ -171,6 +172,7 @@ func (m *Model) FindOne(query interface{}, options *options.FindOneOptionsBuilde } qqn := ModelRegistry.new_(m.typeName) idoc, ok := qqn.(IDocument) + idoc.setRaw(raw) qq := &Query{ collection: m.getColl(), diff --git a/query.go b/query.go index 2addf8a..1b7fd57 100644 --- a/query.go +++ b/query.go @@ -159,7 +159,9 @@ func populate(r Reference, rcoll string, rawDoc interface{}, d string, src inter q := bson.M{"_id": rawDoc} reso := DB.Collection(rcoll).FindOne(context.TODO(), q) if !errors.Is(reso.Err(), mongo.ErrNoDocuments) { - reso.Decode(t) + var anotherMap bson.M + reso.Decode(&anotherMap) + reflect.ValueOf(t).Elem().Set(reflect.ValueOf(rerere(anotherMap, tto)).Elem()) } hatred := rv if hatred.Kind() == reflect.Pointer { @@ -227,6 +229,49 @@ func (q *Query) LoadFile(fields ...string) *Query { return q } +func readFields(field string, m *Model) (Reference, string) { + var r Reference + var keptKey string + if m == nil { + return r, keptKey + } + for k2, v := range m.references { + if strings.HasPrefix(k2, field) { + r = v + keptKey = k2 + break + } else if _, ok := m.references[field]; !ok { + splitSegs := strings.Split(field, ".") + for ii := 0; ii < len(splitSegs)-1; ii++ { + mr, ok2 := m.references[splitSegs[ii]] + if ok2 { + _, sec, _ := ModelRegistry.HasByName(mr.Model) + if sec != nil { + refff, ok3 := sec.references[splitSegs[ii+1]] + if ok3 { + r = refff + keptKey = k2 + break + } else { + joined := strings.Join(splitSegs[ii+1:], ".") + inner1, innerKey := readFields(joined, sec) + if inner1.exists { + r = inner1 + keptKey = innerKey + } + break + } + } + } + } + } + if keptKey != "" { + break + } + } + return r, keptKey +} + // Populate populates document references via reflection func (q *Query) Populate(fields ...string) *Query { _, cm, _ := ModelRegistry.HasByName(q.model.typeName) @@ -236,14 +281,7 @@ func (q *Query) Populate(fields ...string) *Query { for _, field := range fields { // 0 = fieldname, 1 = typename, 2 = bson name - var r Reference - - for k2, v := range cm.references { - if strings.HasPrefix(k2, field) { - r = v - break - } - } + r, keptKey := readFields(field, cm) if r.exists { // get self @@ -275,6 +313,11 @@ func (q *Query) Populate(fields ...string) *Query { } src := ref.Index(i).Interface() inter := populate(r, refColl.collection, val2, field, src) + aid, docOk := inter.(IDocument) + if docOk { + aid.markPopulated(keptKey) + aid.markPopulated(field) + } if reflect.ValueOf(inter).Kind() == reflect.Pointer { slic.Elem().Set(reflect.Append(slic.Elem(), reflect.ValueOf(inter))) } else { @@ -347,7 +390,14 @@ func rerere(input interface{}, resType reflect.Type) interface{} { if resType.Kind() == reflect.Pointer { resType = resType.Elem() } - resV := reflect.New(resType) + var resV reflect.Value + newInstance := ModelRegistry.newForType(resType) + if newInstance == nil { + resV = reflect.New(resType) + } else { + resV = reflect.ValueOf(newInstance) + } + var rve = resV if rve.Kind() == reflect.Pointer { rve = resV.Elem() diff --git a/registry.go b/registry.go index c389f6f..9ff8df8 100644 --- a/registry.go +++ b/registry.go @@ -167,7 +167,7 @@ func parseTags(t reflect.Type, v reflect.Value, lastParsed string, eqCount int) break } if refTag, ok := tags.Get("ref"); ok == nil { - sname := sft.Name + "@" + refTag.Name + sname := sft.Name refs[sname] = makeRef(i, refTag.Name, sft.Name, sft.Type) } if gtag, ok := tags.Get("gridfs"); ok == nil { @@ -244,6 +244,10 @@ func (r TModelRegistry) new_(n string) interface{} { return nil } +func (r TModelRegistry) newForType(rt reflect.Type) interface{} { + return r.new_(rt.Name()) +} + func (r TModelRegistry) Get(name string) *Model { model, ok := r[name] if !ok {