I am working in golang and the mongo driver. I am having a tough time understanding the proper way to go about the following
- Count the data (Done)
- Filter the data (Done)
- Decode to Count + Results (Don’t understand)
I find that my below code seems a bit hacked. Is this the expected path to work with mongodb aggreegates?
func (in *Instance) ListProjects(ctx context.Context, orgID string, filters []*Filter, offset int32, limit int32) ([]*model.Project, int, error) {
in.logger.Info("list_projects called with project_name")
filter := ParseFilters(filters, in.config.Filters.AuthorizedFields)
off := int64(offset)
lim := int64(limit)
pipeline := mongo.Pipeline{
{{Key: "$match", Value: filter}},
{{Key: "$facet", Value: bson.M{
"total": []bson.M{{"$count": "total"}},
"results": []bson.M{
{"$skip": off},
{"$limit": lim},
},
}}},
}
cur, err := in.db.
Database(in.config.Database.Name).
Collection("projects").
Aggregate(ctx, pipeline)
if err != nil {
return nil, 0, err
}
defer cur.Close(context.TODO())
projects := make([]*model.Project, 0)
total := 0
for cur.Next(context.TODO()) {
var result bson.M
err := cur.Decode(&result)
if err != nil {
in.logger.Error(err)
continue
}
for _, v := range result {
switch vv := v.(type) {
case bson.M:
for key, val := range vv {
if key == "total" {
total = int(val.(float64))
} else if key == "results" {
results := val.([]interface{})
for _, item := range results {
data := item.(bson.M)
dataD, err := bson.Marshal(data)
if err != nil {
in.logger.Error(err)
continue
}
var project model.Project
err = bson.Unmarshal(dataD, &project)
if err != nil {
in.logger.Error(err)
continue
}
projects = append(projects, &project)
}
}
}
}
}
}
return projects, total, nil
}