Reputation: 2692
I have a db full of data objects similar to books. This applies to book editions too, so if Book A has been printed 9 times, there are 9 examples of it in my database. What links these 9 examples is they have one id, say book_id
. In my search results, I want to discard all results with the same book_id
except one, the one with the most recent published_date
. Thing is, I'm not sure how to get the aggregation to work properly. Here's what I have now:
return Book.aggregate([
{ $match: generateMLabQuery(rawQuery) },
{ $group: { _id: '$book_id' } },
The first match is simply doing normal matching things, like searching by author or genre or whatever. I was under the impression that $group
would then compress all the results by unique book_id
, but it's not the case, since what I get returned is simply an array of items that look like { _id: earg684rthae68g486e }
. How do I get it to return the full Book document, but with all old releases discarded?
Upvotes: 0
Views: 71
Reputation: 1143
Since the link between these books is 'book_id', it's clear that you need to group by 'book_id' field, that means for every 'book_id', you'll get an array of books.
return Book.aggregate([
{ $match: generateMLabQuery(rawQuery) },
{
$group: {
_id: "$book_id",
books: {
$push: "$$ROOT"
}
}
}
])
The above will give you an array of documents for each book_id in the books field.
But you only need one book for each book_id and that needs to be the one with the latest 'published_date', so if you sort the results on the basis of 'published_date' in descending order, you can just get the first object of the array everytime.
return Book.aggregate([
{ $match: generateMLabQuery(rawQuery) },
{
$sort: {
"published_date": -1
}
},
{
$group: {
_id: "$book_id",
books: {
$first: "$$ROOT"
}
}
}
])
Upvotes: 1
Reputation: 11291
Group creates new objects; you can manipulate $first
/ $last
accumulator operators to digest fields you need, and then $project
them:
return Book.aggregate([
{ $match: generateMLabQuery(rawQuery) },
{
$group: {
_id: '$book_id',
published_date: { $last: '$published_date' },
title: { $first: '$title' },
author: { $first: '$author' }
}
},
{
$project: {
_id: '$id',
book_id: '$_id',
published_date: 1,
title: 1,
author: 1
}
}
])
Upvotes: 0