Поскольку ваш вопрос в настоящее время остается неясным, я действительно надеюсь, что вы имеете в виду, что хотите указать два ключа Site
и 2 ключа Software
, потому что это хороший и простой ответ, который вы можете просто добавить к своей фазе $match, как в:
{$match: {
group_id: "20ea74df4f7074b33b520000",
tracked_item_name: {$in: ['Twitter', 'Facebook', 'Word', 'Excel' ] }
}},
И мы все можем радоваться и радоваться ;)
Однако, если ваш вопрос носит более дьявольский характер, например, получение двух лучших записей Sites
и Software
из результата по продолжительности, то мы очень благодарны вам за создание этой мерзости.
Предупреждение:
Ваш пробег может варьироваться в зависимости от того, что вы на самом деле хотите сделать, или от того, собирается ли это взорваться из-за размера ваших результатов. Но это следует в качестве примера того, что вас ждет:
db.collection.aggregate([
// Match items first to reduce the set
{$match: {group_id: "20ea74df4f7074b33b520000" }},
// Group on the types and "sum" of duration
{$group: {
_id: {
tracked_item_type: "$tracked_item_type",
tracked_item_name: "$tracked_item_name"
},
duration: {$sum: "$duration"}
}},
// Sort by type and duration descending
{$sort: { "_id.tracked_item_type": 1, duration: -1 }},
/* The fun part */
// Re-shape results to "sites" and "software" arrays
{$group: {
_id: null,
sites: {$push:
{$cond: [
{$eq: ["$_id.tracked_item_type", "Site" ]},
{ _id: "$_id", duration: "$duration" },
null
]}
},
software: {$push:
{$cond: [
{$eq: ["$_id.tracked_item_type", "Software" ]},
{ _id: "$_id", duration: "$duration" },
null
]}
}
}},
// Remove the null values for "software"
{$unwind: "$software"},
{$match: { software: {$ne: null} }},
{$group: {
_id: "$_id",
software: {$push: "$software"},
sites: {$first: "$sites"}
}},
// Remove the null values for "sites"
{$unwind: "$sites"},
{$match: { sites: {$ne: null} }},
{$group: {
_id: "$_id",
software: {$first: "$software"},
sites: {$push: "$sites"}
}},
// Project out software and limit to the *top* 2 results
{$unwind: "$software"},
{$project: {
_id: 0,
_id: { _id: "$software._id", duration: "$software.duration" },
sites: "$sites"
}},
{$limit : 2},
// Project sites, grouping multiple software per key, requires a sort
// then limit the *top* 2 results
{$unwind: "$sites"},
{$group: {
_id: { _id: "$sites._id", duration: "$sites.duration" },
software: {$push: "$_id" }
}},
{$sort: { "_id.duration": -1 }},
{$limit: 2}
])
Теперь это приводит к *не совсем чистому набору результатов, который был бы идеальным, но это то, с чем можно работать программно, и это лучше, чем фильтрация предыдущих результатов в цикле. (Мои данные из тестирования)
{
"result" : [
{
"_id" : {
"_id" : {
"tracked_item_type" : "Site",
"tracked_item_name" : "Digital Blasphemy"
},
"duration" : 8000
},
"software" : [
{
"_id" : {
"tracked_item_type" : "Software",
"tracked_item_name" : "Word"
},
"duration" : 9540
},
{
"_id" : {
"tracked_item_type" : "Software",
"tracked_item_name" : "Notepad"
},
"duration" : 4000
}
]
},
{
"_id" : {
"_id" : {
"tracked_item_type" : "Site",
"tracked_item_name" : "Facebook"
},
"duration" : 7920
},
"software" : [
{
"_id" : {
"tracked_item_type" : "Software",
"tracked_item_name" : "Word"
},
"duration" : 9540
},
{
"_id" : {
"tracked_item_type" : "Software",
"tracked_item_name" : "Notepad"
},
"duration" : 4000
}
]
}
],
"ok" : 1
}
Итак, вы видите, что вы получаете 2 верхних элемента Sites
в массиве, в каждый из которых встроены 2 верхних элемента Software
. Сама агрегация не может прояснить это, потому что нам нужно будет повторно объединить элементы, которые мы разделили, чтобы сделать это, и пока нет оператора, который мы могли бы использовать для этого. действие.
Но это было весело. Это не полностью способ, но большая часть пути, и превращение этого в ответ из 4 документов было бы относительно тривиальным кодом. Но голова болит уже.
person
Neil Lunn
schedule
21.02.2014