MongoDB - orderby syntax breaks statement - mongodb

The following query works until I add the orderby statement, but when I try to run after adding it an exception is thrown
db.games.aggregate([
{$unwind: "$games"},
{$project: {_id: 0, year: {$substr: ["$join_date", 0, 4]},
status: 1,
games: 1}},
{$match: {status: {$ne: "disabled"}}},
{$group: {_id: {"Year": "$year", code: "$games.code"}, "AverageWins": {$avg: "$games.wins"}}},
{$orderby: {"AverageWins": -1}}
])
Can anyone help please?

Related

MongoDB $group + $project + weekly average

I'm trying to get the average of a puntations for some stores weekly in Mongo but it don't work. Could u help me?
db.collection.aggregate(
[
{$match:{storeId:{$in:[
ObjectId("e069d1b76557685b9e235v"),ObjectId("e069d1b76557685b9t7j8n"),
ObjectId("e069d1b76557685b9e2fg6"),ObjectId("e069d1b76557685b9p56r2")
]}}},
{$group:{_id:"$storeId", week: { date: new Date("$createdAt") }, totalPoints: {$sum: "$points"}, averagePoints: {$avg: "$points"}} },
{$sort: {totalPoints:-1}}
])
It doesn't work. But if I delete the part of the week, the code work it but make a wrong average
db.collection.aggregate(
[
{$match:{storeId:{$in:[
ObjectId("e069d1b76557685b9e235v"),ObjectId("e069d1b76557685b9t7j8n"),
ObjectId("e069d1b76557685b9e2fg6"),ObjectId("e069d1b76557685b9p56r2")
]}}},
{$group:{_id:"$storeId", totalPoints: {$sum: "$points"}, averagePoints: {$avg: "$points"}} },
{$sort: {totalPoints:-1}}
])
For groupBy week you can use $week function from mongo and add start Date in $match operation.
db.collection.aggregate(
[
{$match:{storeId:{$in:[
ObjectId("e069d1b76557685b9e235v"),ObjectId("e069d1b76557685b9t7j8n"),
ObjectId("e069d1b76557685b9e2fg6"),ObjectId("e069d1b76557685b9p56r2")
]},
timeStamp: {$gt: ISODate(createdAt)},
}},
{$group:{_id:"$storeId", week: { $week: '$timeStamp'}, totalPoints: {$sum: "$points"}, averagePoints: {$avg: "$points"}} },
{$sort: {totalPoints:-1}}
])

MongoDB max in group results

I grouped results by mvid and the counted number of occurrences in each group.
db.some_details.aggregate([
{$group: {_id: "$mvid", count: {$sum: 1}}}
])
Now, I would like to select group with max count. Here is my naive guess:
db.some_details.aggregate([
{$group: {_id: "$mvid", count: {$sum: 1}}},
{$max: "count"}
])
It, obviously, generates an error. I need to use max with group, but I don't have anything to group on.
What also would work is sorting the result and then using only the first element:
db.some_details.aggregate([
{$group: {_id: "$mvid", count: {$sum: 1}}},
{$sort: {"count": -1}},
{$limit: 1 }
])
The advantage that I see compared to chridam's solution is that you also get the id of the group with the maximum count, but I expect it to be slower (not tested).
The aggregation pipeline allows you to could include another $group operator pipeline that would give you the maximum count of all the groups:
db.some_details.aggregate([
{
$group: {
_id: "$mvid",
count: { $sum: 1 }
}
},
{
$group: {
_id: 0,
maxCount: { $max: "$count" }
}
}
])

mongoDB, sum many values query

I have a list of items, and I want mongoDB return the result of the sum of their price.
Schema = {
_id: ObjectId,
price: Integer,
}
I'm trying using the aggregation framework, but I can't figure out how correctly use it.
Here an example
db.items.aggregate([
{$match: {_id: {$in: [103070,103069]}}},
{$unwind: "$items"},
{$group: {_id: "$items", count: {$sum: "$items.price"}}},
{$project: {_id: 1}}
])
you are not correctly using the $in operator... $in is used to find elements inside an array, in this case you should use $gte (greater than equal), $lte (less then equal)... Your schema simply don't have "nodeId"... $unwind is used when you have an array inside the document what I presume is not the case... If i understand the query should be something like:
db.items.aggregate([
{$match : {_id : { $gte : 103069, $lte : 103070 } } },
{$group: {_id: null, count: {$sum: "$price"}}},
{$project: {_id: 0, count : 1}}
])

Get chain of nested documents using MongoDB aggregation framework

Suppose there is a document, that contains an array of documents each of which in turn contains an array of documents, like
{_id: 1, level1: [
{_id: 10, level2: [
{_id: 100},
{_id: 101},
{_id: 102},
]},
{_id: 11, level2: [
{_id: 103},
{_id: 104},
{_id: 105},
]},
{_id: 12, level2: [
{_id: 106},
{_id: 107},
{_id: 108},
]}
]}
and there is an _id = 101 of some inner (third level) document, that I want to search for. I would like to get the inner document and all the enclosing documents in one result, i.e.
{
doc1: {_id: 1, level1: [
{_id: 10, level2: [
{_id: 100},
{_id: 101},
{_id: 102},
]},
{_id: 11, level2: [
{_id: 103},
{_id: 104},
{_id: 105},
]},
{_id: 12, level2: [
{_id: 106},
{_id: 107},
{_id: 108},
]}
]},
doc2: {_id: 10, level2: [
{_id: 100},
{_id: 101},
{_id: 102},
]},
doc3: {_id: 101}
}
Is it possible to achieve this using the Aggregation Framework?

Trying to extract the $first document from collection

After piping various documents through the aggregate framework I finally have the resultant documents.
The problem now is that I only want the $first and $last document.
The final document looks like this (huge list):
...
{
"_id" : "Kaila Deibler",
"count" : 406
},
{
"_id" : "Jessika Dagenais",
"count" : 406
},
{
"_id" : "Tamika Schildgen",
"count" : 404
},
...
The mongo shell command that I used to produce the document is:
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}}}, {$sort: {count: -1}}])
But I only need the first and last document so I attempted something like this:
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}}}, {$sort: {count: -1}}, {$first: "$_id"}])
I tried other implementations but can't seem to figure out when/where to implement $first and $last
Any suggestions?
$first and $last are aggregation functions in the $group pipeline, which means you need to use them inside the $group document.
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}, first: {$first:"$_id"}}}, {$sort: {count: -1}}])
Similarly for $last
You can find an example that shows this here
Here is my own answer to this question:
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}}}, {$sort: {count: -1}}, {$group: {_id: "$_id.comments.author", first: {$first: "$_id"}, last: {$last: "_id"}}}])
Since I want to pull the first and last document after the sort I have to apply another $group with $first and $last. The result:
{
"result" : [
{
"_id" : null,
"first" : "Elizabet Kleine",
"last" : "Mariela Sherer"
}
],
"ok" : 1
}
Note the "_id" : null. Is this necessary?
If anyone has a better solution please share.