Search code examples
mongodbgostructmongo-go

Golang / MongoDB Group Aggregate returning zero values


I'm trying to get a list of unique days and years contained in a MongoDB table, and while I'm getting back the right number of values - all the contents are zero.

In brief, I'm expecting:

{ 12 1 },{ 1 6},{ 1 7}

but I'm getting:

{ 0 0 },{ 0 0 },{ 0 0 }

What am I missing?


Code and Other Info:

The following is my MongoDB table:

{
    "_id" : ObjectId("5fecc811698418c18231af40"),
    "year" : 2020,
    "month" : 12,
    "day" : 30,
}

The struct I'm using to contain the data:

type Test struct {
    Year int `bson:"year"`
    Month int `bson:"month"`
}

And, lastly, my code:

func getEntryDatesHandler(w http.ResponseWriter, r *http.Request) {
    pipelineResult := make([]Test, 0)
    pipeline := make([]bson.M, 0)
    groupStage := bson.M{
        "$group": bson.M{
            "_id": bson.M{
                "year": "$year",
                "month": "$month",
            },
        },
    }

    pipeline = append(pipeline, groupStage)

    data, err := collection.Aggregate(context.Background(), pipeline)

    if err != nil {
        log.Println("error: ", err.Error())
        fmt.Errorf("failed to execute aggregation %s", err.Error())
        return
    }
    err = data.All(context.Background(), &pipelineResult)

    if err != nil {
        log.Println(err.Error())
        fmt.Errorf("failed to decode results", err.Error())
        return
    }
    fmt.Println(pipelineResult)
}

I've verified that the following query works using Robo 3T, but my attempts to directly convert it ended with { 0 0 } as the returned value.

db.getCollection('entries').aggregate([
{$group: {
    _id: null,
    year: {$addToSet: '$year'},
    mont: {$addToSet: '$month'}
    }}
])

Thank you in advance!


Solution

  • Your aggregation transforms the documents, you group them, and you group the year and month fields into _id. Your Test no longer models the result documents.

    Your results may be modeled with a Result struct like this:

    type Test struct {
        Year  int `bson:"year"`
        Month int `bson:"month"`
    }
    
    type Result struct {
        ID Test `bson:"_id"`
    }
    

    And use a slice of Result for the results:

    pipelineResult := make([]Result, 0)
    

    Note: if you don't know the structure of the result documents, you may always use bson.M to model them and inspect them:

    pipelineResult := make([]bson.M, 0)