$ группа по 8 записей с агрегацией - PullRequest
0 голосов
/ 04 января 2019

у меня под коллекцией

{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-01T07:15:32.335Z")
},
{
    "fare" : 32,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-01T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-02T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-03T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-04T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-05T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-06T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-07T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-08T08:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-09T08:15:32.335Z")
}

Мне нужно сделать агрегацию, которая делит эти записи на пару из каждых 8 записей, а также добавляет fare записей, имеющих одинаковую дату. В вышеуказанную дату с 2019-01-01 имеет два fares

Мой ожидаемый результат

{ data: [
{
    "fare" : 44,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-02T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-03T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-04T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-05T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-06T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-07T07:15:32.335Z")
},{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-08T08:15:32.335Z")
}],
data:[{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-09T08:15:32.335Z")
}
] }

Ответы [ 2 ]

0 голосов
/ 05 января 2019

Вы можете использовать агрегацию ниже:

db.col.aggregate([
    {
        $group: {
            _id: { d: { $dayOfMonth: "$createdAt" }, m: { $month: "$createdAt" }, y: { $year: "$createdAt" } },
            fare: { $sum: "$fare" },
            paymentMode: { $first: "$paymentMode" },
            rideType: { $first: "$rideType" },
            userId: { $first: "$userId" },
            createdAt: { $first: "$createdAt" },
        }
    },
    {
        $sort: { createdAt: 1 }
    },
    {
        $project: {
            _id: 0
        }
    },
    {
        $group: {
            _id: null,
            docs: { $push: "$$ROOT" }
        }
    },
    {
        $project: {
            docs: {
                $map: {
                    input: { $range: [0,  { $ceil: { $divide: [ { $size: "$docs" }, 8 ] } } ] },
                    as: "arrayStart",
                    in: {
                        $slice: [ "$docs", { $multiply: [ "$$arrayStart", 8 ] }, 8 ]
                    }
                }
            }
        }
    },
    {
        $unwind: "$docs"
    }
])

Обычно вы хотите суммировать fares по дням, поэтому вам нужно получить этот день на основе типа даты, используя $ dayOfMonth , $ month и $ year операторов.Затем вам нужно получить 8-элементные сегменты, чтобы вы могли объединить все документы в один массив ( $ group с _id, установленным в null).Затем вы можете просто рассчитать, сколько «сегментов» вам нужно (используя $ ceil и $ Делить ) и массив $ slice long в массивы из 8 элементов.На последнем шаге вы можете использовать $ unwind , чтобы получить массив из 8 элементов в конечном документе.Выход:

{
    "_id" : null,
    "docs" : [
        {
            "fare" : 44,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-01T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-02T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-03T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-04T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-05T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-06T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-07T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-08T08:15:32.335Z")
        }
    ]
}
{
    "_id" : null,
    "docs" : [
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-09T08:15:32.335Z")
        }
    ]
}
0 голосов
/ 04 января 2019

Если я правильно понимаю, вы сможете использовать $ bucketAuto конвейер вместо обычного группового шага.Для этого вам, возможно, придется предварительно рассчитать количество необходимых сегментов на основе количества документов.Например, если число равно 84, то значение bucketCount будет примерно равно ceil(84/8) = 11.Я пока не нашел элегантного способа сделать это в той же агрегации.

ОБНОВЛЕНИЕ: Вот пример размещения ваших документов в двух корзинах

db.getCollection('probands').aggregate([
{   $sort : {'_id' : -1}}, // not necessary, but probably nice
{
    $bucketAuto : {
        groupBy: '$_id', // this create "groups" of one element each
        buckets: 2, // calculate this value beforehand
        output: {
            data : {
                $push : { // pushes the wanted fields into the data array
                    '_id': '$_id',
                    'fare' : '$fare',
                    'paymentMode' : '$paymentMode',
                    'createdAt' : '$createdAt',
                    'rideType': '$rideType',
                    'userId': '$userId',
                }
            }
        }
    }
},
{ $project: {_id: 0, data : 1}}
])

Расчет тарифа - это другой вопрос, но, вероятно, он проще, чем при использовании обычного шага $group + $sum.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...