Golang mgo возвращает значение с агрегатом $group

Как получить агрегированный запрос для возврата значений полей, используемых в операторе $group.

Код:

type TheGroup struct{
    Id bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"` 
    Totalamount int
    Dayofyear int
    Actualyear string
    Transactiondate string
    Count int
}

var results []TheGroup

o1 := bson.M{"$match" :bson.M{"transactiontype": transactiontype},}
o2 := bson.M{"$group" : bson.M{"_id": bson.M{"day": "$dayofyear", "year":"$actualyear"},"totalamount":bson.M{"$sum":"$qty"}, "count":bson.M{"$sum":1}},}
operations := []bson.M{o1, o2}
pipe := collection.Pipe(operations)
err1 := pipe.All(&results)

if err := json.NewEncoder(w).Encode(results); err != nil {
panic(err)
}

Результат выглядит следующим образом:

[{"Totalamount":2061,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":679},{"Totalamount":8705,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":2145},{"Totalamount":8156,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":2806},{"Totalamount":9865,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":3294},{"Totalamount":9619,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":3102},{"Totalamount":9975,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":3457},{"Totalamount":14839,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":4036},{"Totalamount":5100,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":1699},{"Totalamount":9649,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":2854},{"Totalamount":11457,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":3220},{"Totalamount":12643,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":3860},{"Totalamount":10301,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":3620},{"Totalamount":7681,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":2816},{"Totalamount":8130,"Dayofyear":0,"Actualyear":"","Transactiondate":"","Count":3023}]

Я думаю, что понимаю, почему Dayofyear / Actualyear не заполняются, потому что, поскольку нет агрегации значений документа, поскольку совпадающие документы просматриваются группой $, но как мне заставить их заполнить?


person mommabear    schedule 15.02.2016    source источник
comment
Почему у вас нет _id в выводе? dayofyear и actualyear должны быть в _id.   -  person dgiugg    schedule 15.02.2016
comment
Я добавил, как генерируется вывод. Должен ли я сделать это по-другому?   -  person mommabear    schedule 15.02.2016


Ответы (1)


Запуск следующего конвейера в оболочке mongo должен дать вам правильный результат:

pipeline = [
    {
        "$match": { "transactiontype": transactiontype }
    },
    { 
        "$group": {
            "_id": {
                "year": { "$year": "$transactiondate" },
                "dayOfYear": { "$dayOfYear": "$transactiondate" }               
            },
            "totalamount": { "$sum": "$qty" }, 
            "count": { "$sum": 1 },
            "date": { "$first": "$transactiondate"}
        }
    },
    {
        "$project": {
            "_id": 0,
            "totalamount": 1,
            "dayOfYear": "$_id.dayOfYear",
            "actualyear": { "$substr": [ "$_id.year", 0, 4 ] },
            "transactiondate": { 
                "$dateToString": { "format": "%Y-%m-%d %H:%M", "date": "$date" } 
            },
            "count": 1
        }
    }
]
db.collection.aggregate(pipeline)

из которых следует эквивалентное выражение mGo (непроверено):

pipeline := []bson.M{   
    bson.M{
        "$match": bson.M{ "transactiontype": transactiontype }
    },
    bson.M{
        "$group": bson.M{
            "_id": bson.M{
                "year": bson.M{ "$year": "$transactiondate" },
                "dayOfYear": bson.M{ "$dayOfYear": "$transactiondate" }             
            },
            "totalamount": bson.M{ "$sum": "$qty" }, 
            "count": bson.M{ "$sum": 1 },
            "date": bson.M{ "$first": "$transactiondate"}
        }
    },
    bson.M{
        "$project": bson.M{
            "_id": 0,
            "totalamount": 1,
            "dayOfYear": "$_id.dayOfYear",
            "actualyear": bson.M{ "$substr": []interface{}{ "$_id.year", 0, 4 } },
            "transactiondate": bson.M{ 
                "$dateToString": bson.M{ "format": "%Y-%m-%d %H:%M", "date": "$date" } 
            },
            "count": 1
        }
    }   
}

pipe := collection.Pipe(pipeline)
person chridam    schedule 08.03.2016
comment
Я получаю cannot use bson.M literal (type bson.M) as type bson.D in array or slice literal (аналогичный случай) - person arnoudhgz; 22.11.2016
comment
@arnoudhgz Измените bson.D на bson.M, который должен скомпилироваться. - person chridam; 22.11.2016