Reputation: 8376
I have a collection with documents in this schema (yep, I know this is schemaless world though):
{
name: "Real Colicos",
fee: 123,
creator: {},
participants: [{},{}]
}
So, I need a query where I can get first groups sorted by participants count. Of course I could have a participantsCount attribute and increment it at update by using $inc
but I feel it's a naive approach. Is this aggregation or map reduce realm?
aggregate
:From docs I could take this:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
}
}
])
This works. Now I wonder, how can I paginate the search, order by participantsCount and include only some document properties?
I've tried:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
},
$skip: 10,
$limit: 5,
$sort: {participantsCount: -1},
$match: {isPrivate: false}
}
],
function (err, results) {
console.log(results);
}
);
But throws undefined
as result.
Also:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}},
{$match: {isPrivate: false}}
}
],
function (err, results) {
console.log(results);
}
);
Which is throwing an empty array.
And even:
db.groups.aggregate(
[
{$project: {name: 1, isPrivate: 1, participantsCount: {$size: "$participants"}}},
{$match: {isPrivate: false}},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}}
],
function (err, results) {
console.log(results);
}
);
Which also throws an empty array.
Upvotes: 0
Views: 2595
Reputation: 8376
From docs:
The aggregation pipeline is a framework for data aggregation modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into an aggregated results.
If your aggregation operation requires only a subset of the data in a collection, use the $match, $limit, and $skip stages to restrict the documents that enter at the beginning of the pipeline.
So this means a pipeline is processed to get the wanted results. And as second paragraph suggests, order in pipeline processing matters.
This is how it must look like:
collection.aggregate(
[
{$match: {isPrivate: false}},
{$skip: 0},
{$limit: 2},
{$project: {name: 1, participantsCount: {$size: "$participants"}}},
{$sort: {participantsCount: -1}}
]
);
Upvotes: 1
Reputation: 41
I can see two immediate problems:
db.groups.aggregate(
[
{$project: {name: 1, participantsCount: {$size: "$participants"}}},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}},
{$match: {isPrivate: false}}
],
function (err, results) {
console.log(results);
}
);
Upvotes: 2