package mongo import ( "context" "time" "fmt" "go.mongodb.org/mongo-driver/v2/bson" "github.com/matoous/go-nanoid/v2" // "git.gsuntres.com/boxtep/boxtep/core" ) const alphabet = "0123456789abcdefghijclmnopqrstuvwxyz" const maxLen = 10 // InsertOneWithStruct can be used to insert defined structs. func (c *MongoClient) InsertOneFromStruct(ctx context.Context, database, name string, data any) (bson.M, error) { o, err := ToMap(data) if err != nil { return nil, err } return c.InsertOne(ctx, database, name, o) } // InsertOne will add missing ids and the created date before saving to the database. func (c *MongoClient) InsertOne(ctx context.Context, database, name string, data bson.M) (bson.M, error) { collection := c.GetCollection(database, name) prepareForInsert(data, c.GetIdPrefix(name)) if _, err := collection.InsertOne(ctx, data); err != nil { return nil, err } return data, nil } // prepareForInsert takes a map[string]any and: // * adds a new _id if property does not exist or is an empty string // * adds/updates property created_at using the current timestamp. func prepareForInsert(data bson.M, idPrefix string) { ensureId(data, idPrefix) ensureCreatedAt(data) ensureUpdatedAt(data) } // ensureId adds the id property when missing or when it's an empty string. func ensureId(data bson.M, idPrefix string) string { maybeId, hasId := data["_id"] var id, finalId string if !hasId || maybeId == "" { id, _ = gonanoid.Generate(alphabet, maxLen) if idPrefix != "" { finalId = fmt.Sprintf("%s_%s", idPrefix, id) } else { finalId = id } data["_id"] = finalId } return finalId } func ensureCreatedAt(data bson.M) time.Time { now := time.Now().UTC().Truncate(time.Millisecond) data["created_at"] = now return now } func ensureUpdatedAt(data bson.M) time.Time { now := time.Now().UTC().Truncate(time.Millisecond) data["updated_at"] = now return now }