{"id":10855,"date":"2022-09-25T05:43:36","date_gmt":"2022-09-25T00:13:36","guid":{"rendered":"http:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/"},"modified":"2022-09-25T05:43:36","modified_gmt":"2022-09-25T00:13:36","slug":"solved-mongodb-aggregate-query-or-too-complex","status":"publish","type":"post","link":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/","title":{"rendered":"[Solved] Mongodb aggregate query, or too complex?"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div id=\"answer-35168546\" class=\"answer js-answer accepted-answer js-accepted-answer\" data-answerid=\"35168546\" data-parentid=\"35161734\" data-score=\"3\" data-position-on-page=\"1\" data-highest-scored=\"1\" data-question-has-accepted-highest-score=\"1\" itemprop=\"acceptedAnswer\" itemscope itemtype=\"https:\/\/schema.org\/Answer\">\n<div class=\"post-layout\">\n<div class=\"votecell post-layout--left\"><\/div>\n<div class=\"answercell post-layout--right\">\n<div class=\"s-prose js-post-body\" itemprop=\"text\">\n<p>Though it should have been made more clear in your question, your output sample from source suggests that you are looking for:<\/p>\n<ul>\n<li>Total count of messages per &#8220;uid&#8221;<\/li>\n<li>Distinct count of values in &#8220;to&#8221;<\/li>\n<li>Distinct count of values in &#8220;from&#8221;<\/li>\n<li>Summary of counts per &#8220;hour&#8221; for each &#8220;uid&#8221;<\/li>\n<\/ul>\n<p>This is all possible in a single aggregation statement, and it just takes some careful management of the distinct lists and then some manipulation to map results for each hour in a 24 hour period.<\/p>\n<p>The best approach here is aided by operators introduced in MongoDB 3.2:<\/p>\n<pre class=\"lang-js prettyprint-override\"><code>db.collection.aggregate([\n    \/\/ First group by hour within \"uid\" and keep distinct \"to\" and \"from\"\n    { \"$group\": {\n        \"_id\": {\n            \"uid\": \"$uid\",\n            \"time\": { \"$hour\": \"$timestamp\" }\n        },\n        \"from\": { \"$addToSet\": \"$from\" },\n        \"to\": { \"$addToSet\": \"$to\" },\n        \"count\": { \"$sum\": 1 }\n    }},\n\n    \/\/ Roll-up to \"uid\" and keep each hour in an array\n    { \"$group\": {\n        \"_id\": \"$_id.uid\",\n        \"total\": { \"$sum\": \"$count\" },\n        \"from\": { \"$addToSet\": \"$from\" },\n        \"to\": { \"$addToSet\": \"$to\" },\n        \"temp_hours\": { \n            \"$push\": {\n                \"index\": \"$_id.time\",\n                \"count\": \"$count\"\n            }\n        }\n     }},\n\n     \/\/ Getting distinct \"to\" and \"from\" requires a double unwind of arrays\n     { \"$unwind\": \"$to\" },\n     { \"$unwind\": \"$to\" },\n     { \"$unwind\": \"$from\" },\n     { \"$unwind\": \"$from\" },\n\n     \/\/ And then adding back to sets for distinct\n     { \"$group\": {\n        \"_id\": \"$_id\",\n        \"total\": { \"$first\": \"$total\" },\n        \"from\": { \"$addToSet\": \"$from\" },\n        \"to\": { \"$addToSet\": \"$to\" },\n        \"temp_hours\": { \"$first\": \"$temp_hours\" }\n     }},\n\n     \/\/ Map out for each hour and count size of distinct lists\n     { \"$project\": {\n        \"count\": \"$total\",\n        \"from_count\": { \"$size\": \"$from\" },\n        \"to_count\": { \"$size\": \"$to\" },\n        \"hours\": {\n            \"$map\": {\n                \"input\": [\n                     00,01,02,03,04,05,06,07,08,09,10,11,\n                     12,13,14,15,16,17,18,19,20,21,22,23\n                 ],\n                 \"as\": \"el\",\n                 \"in\": {\n                      \"$ifNull\": [\n                          { \"$arrayElemAt\": [\n                              { \"$map\": {\n                                  \"input\": { \"$filter\": {\n                                     \"input\": \"$temp_hours\",\n                                     \"as\": \"tmp\",\n                                     \"cond\": {\n                                         \"$eq\": [ \"$$el\", \"$$tmp.index\" ]\n                                     }\n                                  }},\n                                 \"as\": \"out\",\n                                 \"in\": \"$$out.count\"\n                              }},\n                              0\n                          ]},\n                          0\n                      ]\n                 }\n            }\n        }\n     }},\n\n     \/\/ Optionally sort in \"uid\" order\n     { \"$sort\": { \"_id\": 1 } }\n ])\n<\/code><\/pre>\n<p>Prior MongoDB 3.2 you need to get a bit more involved to map the array content for all hours in the day:<\/p>\n<pre class=\"lang-js prettyprint-override\"><code>db.collection.aggregate([\n\n    \/\/ First group by hour within \"uid\" and keep distinct \"to\" and \"from\"\n    { \"$group\": {\n        \"_id\": {\n            \"uid\": \"$uid\",\n            \"time\": { \"$hour\": \"$timestamp\" }\n        },\n        \"from\": { \"$addToSet\": \"$from\" },\n        \"to\": { \"$addToSet\": \"$to\" },\n        \"count\": { \"$sum\": 1 }\n    }},\n\n    \/\/ Roll-up to \"uid\" and keep each hour in an array\n    { \"$group\": {\n        \"_id\": \"$_id.uid\",\n        \"total\": { \"$sum\": \"$count\" },\n        \"from\": { \"$addToSet\": \"$from\" },\n        \"to\": { \"$addToSet\": \"$to\" },\n        \"temp_hours\": { \n            \"$push\": {\n                \"index\": \"$_id.time\",\n                \"count\": \"$count\"\n            }\n        }\n     }},\n\n     \/\/ Getting distinct \"to\" and \"from\" requires a double unwind of arrays\n     { \"$unwind\": \"$to\" },\n     { \"$unwind\": \"$to\" },\n     { \"$unwind\": \"$from\" },\n     { \"$unwind\": \"$from\" },\n\n     \/\/ And then adding back to sets for distinct, also adding the indexes array\n     { \"$group\": {\n        \"_id\": \"$_id\",\n        \"total\": { \"$first\": \"$total\" },\n        \"from\": { \"$addToSet\": \"$from\" },\n        \"to\": { \"$addToSet\": \"$to\" },\n        \"temp_hours\": { \"$first\": \"$temp_hours\" },\n        \"indexes\": { \"$first\": { \"$literal\": [\n                     00,01,02,03,04,05,06,07,08,09,10,11,\n                     12,13,14,15,16,17,18,19,20,21,22,23\n        ] } }\n     }},\n\n     \/\/ Denormalize both arrays\n     { \"$unwind\": \"$temp_hours\" },\n     { \"$unwind\": \"$indexes\" },\n\n     \/\/ Marry up the index entries and keep either the value or 0\n     \/\/ Note you are normalizing the double unwind to distinct index\n     { \"$group\": {\n         \"_id\": {\n             \"_id\": \"$_id\",\n             \"index\": \"$indexes\"\n         },\n         \"total\": { \"$first\": \"$total\" }, \n         \"from\": { \"$first\": \"$from\" },\n         \"to\": { \"$first\": \"$to\" },\n         \"count\": {\n             \"$max\": {\n                 \"$cond\": [\n                     { \"$eq\": [ \"$indexes\", \"$temp_hours.index\" ] },\n                     \"$temp_hours.count\",\n                     0\n                 ]\n             }\n         }\n     }},\n\n     \/\/ Sort to keep index order - !!Important!!         \n     { \"$sort\": { \"_id\": 1 } },\n\n     \/\/ Put the hours into the array and get sizes for other results\n     { \"$group\": {\n         \"_id\": \"$_id._id\",\n         \"count\": { \"$first\": \"$total\" },\n         \"from_count\": { \"$first\": { \"$size\": \"$from\" } },\n         \"to_count\": { \"$first\": { \"$size\": \"$to\" } },\n         \"hours\": { \"$push\": \"$count\" }\n     }},\n\n     \/\/ Optionally sort in \"uid\" order\n     { \"$sort\": { \"_id\": 1 } }\n])\n<\/code><\/pre>\n<p>To break that down, both approaches here follow the same basic steps, with the only real difference occuring on the mapping of &#8220;hours&#8221; for the 24 hour period.<\/p>\n<p>In the first aggregation <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/group\/\"><code>$group<\/code><\/a> stage, the objective is to get results per hour present in the data and for each &#8220;uid&#8221; value. The simple date aggregation operator of <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/hour\/\"><code>$hour<\/code><\/a> helps obtain this value as part of the grouping key.<\/p>\n<p>The <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/addToSet\/\"><code>$addToSet<\/code><\/a> operations are a sort of &#8220;mini-group&#8221; in themselves, and this is allowing to keep the &#8220;distinct sets&#8221; for each of the &#8220;to&#8221; and &#8220;from&#8221; values whilst essentially still grouping per hour.<\/p>\n<p>The next <code>$group<\/code> is more &#8220;organizational&#8221;, as the recorded &#8220;counts&#8221; for each hour are kept in an array whilst rolling up all the data to just be grouped per &#8220;uid&#8221;. This basically gives you all the &#8220;data&#8221; you really need for the result, but of course the <code>$addToSet<\/code> operations here are just adding &#8220;arrays within arrays&#8221; of the distinct sets determined per hour.<\/p>\n<p>In order to get these values as truly distinct lists per each &#8220;uid&#8221; and only, it is necessary to deconstruct each array using <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/unwind\/\"><code>$unwind<\/code><\/a> and then finally group back as just the distinct &#8220;sets&#8221;. The same <code>$addToSet<\/code> compacts this, and the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/first\/\"><code>$first<\/code><\/a> operations just take the &#8220;first&#8221; values of the other fields, which are already all the same for the target &#8220;per uid&#8221; data. We are happy with those, so just keep them as they are.<\/p>\n<p>The final stage(s) here are essentially &#8220;cosmetic&#8221; in nature and can equally be achieved in client side code. Since there is not data present for every single hour interval, it needs to be mapped into an array of values representing each hour. The two approaches here vary on the capabilties of the available operators between versions.<\/p>\n<p>In the MongoDB 3.2 release, there are <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/filter\/\"><code>$filter<\/code><\/a> and <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/arrayElemAt\/\"><code>$arrayElemAt<\/code><\/a> operators that effectively allow you to create the logic to &#8220;transpose&#8221; an input source of all possible index positions ( 24 hours ) into the values that are already determined for the counts fom those hours in the available data. This is basicalyl a &#8220;direct lookup&#8221; of values already recorded for each available hour to see if it exists, where it does the count is transposed into the full array. Where it is not present, a default value of <code>0<\/code> is used in place.<\/p>\n<p>Without those operators, doing this &#8220;match up&#8221; essentially means de-normalizing both arrays ( the recorded data and the full 24 positions ) in order to compare and transpose. This is what is happening in the second approach with a simple comparison of the &#8220;index&#8221; values to see if there was a result for that hour. The <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/max\/\"><code>$max<\/code><\/a> operator here is mainly used because of the two <code>$unwind<\/code> statements, where each recorded value from the source data is going to be reproduced for every possible index position. This &#8220;compacts&#8221; down to just the values that are wanted per &#8220;index hour&#8221;.<\/p>\n<p>In that latter approach it then becomes important to <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/sort\/\"><code>$sort<\/code><\/a> on the grouping <code>_id<\/code> value. This is because it contains the &#8220;index&#8221; position, and that is going to be needed when moving this content back into an array you expect to be orderred. Which is of course the final <code>$group<\/code> stage here where the ordered positions are put into an array with <code>$push<\/code>.<\/p>\n<p>Back to the &#8220;distinct lists&#8221;, the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.mongodb.org\/manual\/reference\/operator\/aggregation\/size\/\"><code>$size<\/code><\/a> operator is used in all cases to determine the &#8220;length&#8221; and therefore &#8220;count&#8221; of distinct values in the lists for &#8220;to&#8221; and &#8220;from&#8221;. This is the only real constraint on MongoDB 2.6 at least, but can otherwise be replaced with simply &#8220;unwinding&#8221; each array individually and then grouping back on the <code>_id<\/code> already present in order to count the array entries in each set. It&#8217;s a basic process, but as you should see the <code>$size<\/code> operator is the better option here for overall performance.<\/p>\n<hr>\n<p>As a final note, your conclusion data is a little off, as possibly the entry with &#8220;ddd&#8221; in &#8220;from&#8221; was intended to also be the same in &#8220;to&#8221;, but is instead recorded as &#8220;bbb&#8221;. This changes the distinct count of the third &#8220;uid&#8221; grouping for &#8220;to&#8221; down by one entry. But of course the logical results given the source data is sound:<\/p>\n<pre class=\"lang-js prettyprint-override\"><code>{ \"_id\" : 1000000, \"count\" : 3, \"from_count\" : 2, \"to_count\" : 2, \"hours\" : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0 ] }\n{ \"_id\" : 2000000, \"count\" : 2, \"from_count\" : 1, \"to_count\" : 1, \"hours\" : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0 ] }\n{ \"_id\" : 3000000, \"count\" : 5, \"from_count\" : 5, \"to_count\" : 4, \"hours\" : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0 ] }\n<\/code><\/pre>\n<p>N.B The source also has a typo with the delimitter being interposed with <code>:<\/code> instead of a comma right after the timestamp on all lines. <\/p>\n<\/p><\/div>\n<div class=\"mt24\"><\/div>\n<\/div>\n<p>            <span class=\"d-none\" itemprop=\"commentCount\"><\/span> <\/p><\/div>\n<\/div>\n<p>[ad_2]<\/p>\n<p>solved Mongodb aggregate query, or too complex? <\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] Though it should have been made more clear in your question, your output sample from source suggests that you are looking for: Total count of messages per &#8220;uid&#8221; Distinct count of values in &#8220;to&#8221; Distinct count of values in &#8220;from&#8221; Summary of counts per &#8220;hour&#8221; for each &#8220;uid&#8221; This is all possible in a &#8230; <a title=\"[Solved] Mongodb aggregate query, or too complex?\" class=\"read-more\" href=\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\" aria-label=\"More on [Solved] Mongodb aggregate query, or too complex?\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[320],"tags":[2979,1128,2978],"class_list":["post-10855","post","type-post","status-publish","format-standard","hentry","category-solved","tag-aggregation-framework","tag-mongodb","tag-mongodb-query"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>[Solved] Mongodb aggregate query, or too complex? - JassWeb<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"[Solved] Mongodb aggregate query, or too complex? - JassWeb\" \/>\n<meta property=\"og:description\" content=\"[ad_1] Though it should have been made more clear in your question, your output sample from source suggests that you are looking for: Total count of messages per &#8220;uid&#8221; Distinct count of values in &#8220;to&#8221; Distinct count of values in &#8220;from&#8221; Summary of counts per &#8220;hour&#8221; for each &#8220;uid&#8221; This is all possible in a ... Read more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\" \/>\n<meta property=\"og:site_name\" content=\"JassWeb\" \/>\n<meta property=\"article:published_time\" content=\"2022-09-25T00:13:36+00:00\" \/>\n<meta name=\"author\" content=\"Kirat\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kirat\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\"},\"author\":{\"name\":\"Kirat\",\"@id\":\"https:\/\/jassweb.com\/solved\/#\/schema\/person\/65c9c7b7958150c0dc8371fa35dd7c31\"},\"headline\":\"[Solved] Mongodb aggregate query, or too complex?\",\"datePublished\":\"2022-09-25T00:13:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\"},\"wordCount\":833,\"publisher\":{\"@id\":\"https:\/\/jassweb.com\/solved\/#organization\"},\"keywords\":[\"aggregation-framework\",\"mongodb\",\"mongodb-query\"],\"articleSection\":[\"Solved\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\",\"url\":\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\",\"name\":\"[Solved] Mongodb aggregate query, or too complex? - JassWeb\",\"isPartOf\":{\"@id\":\"https:\/\/jassweb.com\/solved\/#website\"},\"datePublished\":\"2022-09-25T00:13:36+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/jassweb.com\/solved\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"[Solved] Mongodb aggregate query, or too complex?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/jassweb.com\/solved\/#website\",\"url\":\"https:\/\/jassweb.com\/solved\/\",\"name\":\"JassWeb\",\"description\":\"Build High-quality Websites\",\"publisher\":{\"@id\":\"https:\/\/jassweb.com\/solved\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/jassweb.com\/solved\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/jassweb.com\/solved\/#organization\",\"name\":\"Jass Web\",\"url\":\"https:\/\/jassweb.com\/solved\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/jassweb.com\/solved\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/jassweb.com\/wp-content\/uploads\/2021\/02\/jass-website-logo-1.png\",\"contentUrl\":\"https:\/\/jassweb.com\/wp-content\/uploads\/2021\/02\/jass-website-logo-1.png\",\"width\":693,\"height\":132,\"caption\":\"Jass Web\"},\"image\":{\"@id\":\"https:\/\/jassweb.com\/solved\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/jassweb.com\/solved\/#\/schema\/person\/65c9c7b7958150c0dc8371fa35dd7c31\",\"name\":\"Kirat\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/jassweb.com\/solved\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/jassweb.com\/solved\/wp-content\/litespeed\/avatar\/1261af3c9451399fa1336d28b98ea3bb.jpg?ver=1775798750\",\"contentUrl\":\"https:\/\/jassweb.com\/solved\/wp-content\/litespeed\/avatar\/1261af3c9451399fa1336d28b98ea3bb.jpg?ver=1775798750\",\"caption\":\"Kirat\"},\"sameAs\":[\"http:\/\/jassweb.com\"],\"url\":\"https:\/\/jassweb.com\/solved\/author\/jaspritsinghghumangmail-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"[Solved] Mongodb aggregate query, or too complex? - JassWeb","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/","og_locale":"en_US","og_type":"article","og_title":"[Solved] Mongodb aggregate query, or too complex? - JassWeb","og_description":"[ad_1] Though it should have been made more clear in your question, your output sample from source suggests that you are looking for: Total count of messages per &#8220;uid&#8221; Distinct count of values in &#8220;to&#8221; Distinct count of values in &#8220;from&#8221; Summary of counts per &#8220;hour&#8221; for each &#8220;uid&#8221; This is all possible in a ... Read more","og_url":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/","og_site_name":"JassWeb","article_published_time":"2022-09-25T00:13:36+00:00","author":"Kirat","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Kirat","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/#article","isPartOf":{"@id":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/"},"author":{"name":"Kirat","@id":"https:\/\/jassweb.com\/solved\/#\/schema\/person\/65c9c7b7958150c0dc8371fa35dd7c31"},"headline":"[Solved] Mongodb aggregate query, or too complex?","datePublished":"2022-09-25T00:13:36+00:00","mainEntityOfPage":{"@id":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/"},"wordCount":833,"publisher":{"@id":"https:\/\/jassweb.com\/solved\/#organization"},"keywords":["aggregation-framework","mongodb","mongodb-query"],"articleSection":["Solved"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/","url":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/","name":"[Solved] Mongodb aggregate query, or too complex? - JassWeb","isPartOf":{"@id":"https:\/\/jassweb.com\/solved\/#website"},"datePublished":"2022-09-25T00:13:36+00:00","breadcrumb":{"@id":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/jassweb.com\/solved\/solved-mongodb-aggregate-query-or-too-complex\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/jassweb.com\/solved\/"},{"@type":"ListItem","position":2,"name":"[Solved] Mongodb aggregate query, or too complex?"}]},{"@type":"WebSite","@id":"https:\/\/jassweb.com\/solved\/#website","url":"https:\/\/jassweb.com\/solved\/","name":"JassWeb","description":"Build High-quality Websites","publisher":{"@id":"https:\/\/jassweb.com\/solved\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jassweb.com\/solved\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/jassweb.com\/solved\/#organization","name":"Jass Web","url":"https:\/\/jassweb.com\/solved\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jassweb.com\/solved\/#\/schema\/logo\/image\/","url":"https:\/\/jassweb.com\/wp-content\/uploads\/2021\/02\/jass-website-logo-1.png","contentUrl":"https:\/\/jassweb.com\/wp-content\/uploads\/2021\/02\/jass-website-logo-1.png","width":693,"height":132,"caption":"Jass Web"},"image":{"@id":"https:\/\/jassweb.com\/solved\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/jassweb.com\/solved\/#\/schema\/person\/65c9c7b7958150c0dc8371fa35dd7c31","name":"Kirat","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jassweb.com\/solved\/#\/schema\/person\/image\/","url":"https:\/\/jassweb.com\/solved\/wp-content\/litespeed\/avatar\/1261af3c9451399fa1336d28b98ea3bb.jpg?ver=1775798750","contentUrl":"https:\/\/jassweb.com\/solved\/wp-content\/litespeed\/avatar\/1261af3c9451399fa1336d28b98ea3bb.jpg?ver=1775798750","caption":"Kirat"},"sameAs":["http:\/\/jassweb.com"],"url":"https:\/\/jassweb.com\/solved\/author\/jaspritsinghghumangmail-com\/"}]}},"_links":{"self":[{"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/posts\/10855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/comments?post=10855"}],"version-history":[{"count":0,"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/posts\/10855\/revisions"}],"wp:attachment":[{"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/media?parent=10855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/categories?post=10855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jassweb.com\/solved\/wp-json\/wp\/v2\/tags?post=10855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}