Add timeseries, discriminator

This commit is contained in:
George Suntres
2026-04-17 11:38:12 -04:00
parent cba3e326e8
commit 99b36e577e
18 changed files with 897 additions and 130 deletions

147
main.go
View File

@@ -19,6 +19,10 @@ import (
"git.gsuntres.com/general/sys"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
// WithiSessionFunc will run operations on the database within the same session.
// If this functions returns an error, the system will rollback the transaction.
// Sessions require a resplica set.
@@ -38,14 +42,29 @@ type IMongoClient interface {
GetCollection(database, name string) *mongo.Collection
}
type Timeseries struct {
TimeField string `bson:"timeField"`
MetaField string `bson:"metaField"`
Granularity string `bson:"granularity"`
}
type Discriminator struct {
Field string `bson:"field"`
CtxField string `bson:"ctxField"`
Collection string `bson:"collection"`
Required bool `bson:"required,omitempty"`
}
type CollectionDefinition struct {
Name string `bson:"_name"`
Singular string `bson:"singular"`
Plural string `bson:"plural"`
IdPrefix string `bson:"idPrefix"`
IndexSpecs []map[string]any `bson:"indexSpecs"`
Schema map[string]any `bson:"schema"`
Views map[string]any `bson:"views"`
Name string `bson:"_name"`
Singular string `bson:"singular"`
Plural string `bson:"plural"`
IdPrefix string `bson:"idPrefix"`
IndexSpecs []map[string]any `bson:"indexSpecs"`
Schema map[string]any `bson:"schema"`
Views map[string]any `bson:"views"`
Timeseries *Timeseries `bson:"timeseries,omitempty"`
Discriminator *Discriminator
}
// func (cd *CollectionDefinition) GetSchema(name string)
@@ -75,34 +94,6 @@ func (c *MongoClient) GetIdPrefix(name string) string {
return ""
}
const ADD_DEFINITION_SCHEMA = `
{
"type": "object",
"properties": {
"_name": {
"type": "string"
},
"idPrefix": {
"type": "string"
},
"indexSpecs": {
"type": "array"
},
"singular": {
"type": "string"
},
"system": {
"type": "boolean"
},
"plural": {
"type": "string"
}
},
"required": ["_name", "singular", "plural"],
"additionalProperties": true
}
`
func (c *MongoClient) AddDefinition(data map[string]any) {
if valid := commons.Validate(ADD_DEFINITION_SCHEMA, data); valid != nil {
log.Printf("failed to register data: %v", valid)
@@ -154,6 +145,7 @@ func (c *MongoClient) GetCollection(database, name string) *mongo.Collection {
if ok {
log.Printf("Schema found for %s; will use it", name)
ApplyTimeSeries(cdef, opts)
ApplySchema(cdef, opts)
} else {
log.Printf("No schema for %s", name)
@@ -168,16 +160,28 @@ func (c *MongoClient) GetCollection(database, name string) *mongo.Collection {
collection := db.Collection(name)
c.CreateIndexes(collection, cdef)
c.CreateViews(db, cdef)
return collection
}
}
func ApplyTimeSeries(cdef *CollectionDefinition, opts *options.CreateCollectionOptionsBuilder) {
if cdef.Timeseries != nil {
tsOpts := options.TimeSeries().
SetTimeField(cdef.Timeseries.TimeField).
SetMetaField(cdef.Timeseries.MetaField).
SetGranularity(cdef.Timeseries.Granularity)
opts.SetTimeSeriesOptions(tsOpts)
} else {
log.Printf("No timeseries")
}
}
func ApplySchema(cdef *CollectionDefinition, opts *options.CreateCollectionOptionsBuilder) {
// Add schema validation
if cdef.Schema != nil {
if cdef.Schema != nil && cdef.Timeseries == nil {
schemaBson, err := bson.Marshal(cdef.Schema)
if err != nil {
log.Printf("failed to parse schema: %v", err)
@@ -191,7 +195,7 @@ func ApplySchema(cdef *CollectionDefinition, opts *options.CreateCollectionOptio
opts.SetValidator(validator)
}
} else {
log.Printf("Invalid schema, do nothing.")
log.Printf("Validation disabled")
}
}
@@ -353,3 +357,70 @@ func MapToBsonD(m map[string]any) (bson.D, error) {
return d, nil
}
const ADD_DEFINITION_SCHEMA = `
{
"type": "object",
"properties": {
"_name": {
"type": "string"
},
"idPrefix": {
"type": "string"
},
"indexSpecs": {
"type": "array"
},
"singular": {
"type": "string"
},
"system": {
"type": "boolean"
},
"plural": {
"type": "string"
},
"schema": {
"type": "object"
},
"views": {
"type": "object"
},
"timeseries": {
"type": "object",
"properties": {
"timeField": {
"type": "string"
},
"metaField": {
"type": "string"
},
"granularity": {
"enum": [ "seconds", "minutes", "hours"]
}
},
"required": ["timeField", "metaField", "granularity"]
},
"discriminator": {
"type": "object",
"properties": {
"field": {
"type": "string"
},
"ctxField": {
"type": "string"
},
"collection": {
"type": "string"
},
"required": {
"type": "boolean"
}
},
"required": ["field", "ctxField", "collection"]
}
},
"required": ["_name", "singular", "plural"],
"additionalProperties": true
}
`