В настоящее время я пытаюсь разделить результат агрегации на два разных массива, используя только mongodb.
Моя главная цель - создать два подмножества пользователей с одинаковым распределением в отношении количества взаимодействий, которые они совершили. Для этого я сейчас делаю этот запрос:
db.getCollection('Interaction').aggregate([
{ $group : { _id : "$userId", count: { $sum: 1 }}},
{ $sort : { count : -1 }},
{ $group : { _id :{$mod : [_rand() * 2, 2]}, ids : { $push: "$_id"}}}
}
Моя главная проблема на самом деле заключается в том, что функция _rand () вызывается только один раз во время выполнения агрегации, чтобы все мои результаты содержались только в одном массиве.
Кроме того, случайное распределение не так хорошо. Есть ли способ использовать индекс каждого результата?
Редактировать 1:
После ответа @dnickless у меня все еще есть проблема с распространением в группе groupBy. В идеале я хотел бы сделать что-то вроде этого
db.getCollection('Interaction').aggregate([
{ $group : { _id : "$userId", count: { $sum: 1 }}},
{ $sort : { count : -1 }},
{ $bucket: {
groupBy: { $mod: [ { $indexOfArray : ??? }, 2 ] },
boundaries: [ 0, 1 ],
default: 2,
output: {
"users": { $push: "$_id"}
}
}
}
],
{ allowDiskUse: true })
Это может разделить четный индекс и нечетный индекс на два отдельных массива. Но я хотел бы применить $indexOfArray
к текущему результату агрегирования.
Чтобы дать вам больше контекста, вот моя объектная модель взаимодействия:
{ "_id" : ObjectId("5af01..."), "name" : "WATCH", "date" : ISODate("2018-05-07T09:32:53.219Z") }
Без части ковша у меня получился такой результат:
{ "_id" : "5b1e7f...", "count" : 43.0 }
{ "_id" : "5b1e75...", "count" : 41.0 }
{ "_id" : "5b1e7a...", "count" : 40.0 }
...
Я бы хотел, чтобы мой ответ выглядел так:
{
{ "_id" : 0, "users" : [ "5b1e7f...", "5b1e7a...", ... ] }, // even index results
{ "_id" : 1, "users" : [ "5b1e75...", ... ] } // odd index results
}
Моя конечная цель - разделить моих пользователей на 2 группы с равномерно распределенным количеством взаимодействий.
Редактировать 2:
Наконец-то нашли решение для моей проблемы:
db.getCollection('Interaction').aggregate([
{ $group : { _id : "$userId", count: { $sum: 1 }}},
{ $sort : { count : -1 }},
{ $group : { _id : "whatever" , user : { $push : { _id : "$_id" , count : "$count"}}}},
{ $unwind : { path : "$user" , "includeArrayIndex" : "rank"}},
{ $bucket: {
groupBy: { $mod: [ "$rank" , 2 ] },
boundaries: [ 0, 1 ],
default: 2,
output: {
"users": { $push: "$user._id"}
}
}
}
],
{ allowDiskUse: true })
Вероятно, не самое оптимизированное решение вообще, но все же сделайте свою работу :)
Если у вас есть какие-либо советы, чтобы улучшить его, я все еще заинтересован.