Da Ihre Frage derzeit unklar ist, hoffe ich wirklich, dass Sie damit meinen, dass Sie zwei Site
angeben möchten Schlüssel und 2 Software
Schlüssel, denn das ist eine nette und einfache Antwort, die Sie einfach zu Ihrer $match-Phase hinzufügen können, wie in:
{$match: {
group_id: "20ea74df4f7074b33b520000",
tracked_item_name: {$in: ['Twitter', 'Facebook', 'Word', 'Excel' ] }
}},
Und wir können alle jubeln und uns freuen;)
Wenn Ihre Frage jedoch etwas teuflischer ist, wie zum Beispiel, die Top 2 Site
zu bekommen und Software
Einträge aus dem Ergebnis nach Dauer, dann danken wir Ihnen sehr für das Spawnen dieser Abscheulichkeit .
Warnung:
Ihre Laufleistung kann davon abhängen, was Sie tatsächlich tun möchten oder ob dies durch die schiere Größe Ihrer Ergebnisse in die Luft gesprengt wird. Aber dies folgt als Beispiel dafür, worauf Sie sich einlassen:
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}
])
Das Ergebnis ist nun *nicht genau die sauberen Ergebnisse, die ideal wären, aber es ist etwas, mit dem programmatisch gearbeitet werden kann, und besser als das Filtern der vorherigen Ergebnisse in einer Schleife. (Meine Daten aus dem Test)
{
"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
}
Sie sehen also, Sie erhalten die Top 2 Site
im Array, mit den Top 2 Software
darin eingebettete Elemente. Die Aggregation selbst kann dies nicht weiter aufklären, da wir re-mergen müssten die Elemente, die wir zu diesem Zweck aufteilen, und bis jetzt gibt es keinen Operator, mit dem wir diese Aktion ausführen könnten.
Aber das hat Spaß gemacht. Es ist nicht alles der Weg getan, aber die meisten des Weges, und daraus eine 4-Dokument-Antwort zu machen, wäre relativ trivialer Code. Aber mein Kopf tut schon weh.