Reputation: 926
I have two models, post and vote.
Post schema
title:{
type: String,
required: true,
},
description:{
type: String,
required: true,
},
votes: [
{
type: Schema.Types.ObjectId,
ref: 'Vote'
}
],
Vote Schema
const voteSchema = new Schema({
post:{
type: Schema.Types.ObjectId,
ref: 'Post',
},
value:{
type: Number,
required: true,
},
});
I am trying to sort post by the most value of votes grouped.
Maybe something like this?
var posts = Post.aggregate([{$sort: { $group: votes: {$sum: value} }}
Any help would be appreciated.
Thanks!
Upvotes: 1
Views: 174
Reputation: 334
code sample for retrieving data from two collections with $lookup and sorting
// data preparation, please use drop command in your work with caution
original_id = ObjectId();
db.post.insertOne({"_id":original_id,title:"hotel review"});
db.vote.insertOne({post_id:original_id, vote:22});
//
original_id = ObjectId();
db.post.insertOne({"_id":original_id,title:"movie review"});
db.vote.insertOne({post_id:original_id, vote:99});
//
> db.post.find();
{ "_id" : ObjectId("5f42573349cf5c81666018f5"), "title" : "hotel review" }
{ "_id" : ObjectId("5f42581949cf5c81666018f7"), "title" : "movie review" }
> db.vote.find();
{ "_id" : ObjectId("5f42573349cf5c81666018f6"), "post_id" : ObjectId("5f42573349cf5c81666018f5"), "vote" : 22 }
{ "_id" : ObjectId("5f42581949cf5c81666018f8"), "post_id" : ObjectId("5f42581949cf5c81666018f7"), "vote" : 99 }
> db.post.aggregate([ {$lookup: {from:"vote", localField:"_id", foreignField:"post_id", as:"post_docs" } }, {$sort:{"post_docs.vote":-1}} ]).pretty();
{
"_id" : ObjectId("5f42581949cf5c81666018f7"),
"title" : "movie review",
"post_docs" : [
{
"_id" : ObjectId("5f42581949cf5c81666018f8"),
"post_id" : ObjectId("5f42581949cf5c81666018f7"),
"vote" : 99
}
]
}
{
"_id" : ObjectId("5f42573349cf5c81666018f5"),
"title" : "hotel review",
"post_docs" : [
{
"_id" : ObjectId("5f42573349cf5c81666018f6"),
"post_id" : ObjectId("5f42573349cf5c81666018f5"),
"vote" : 22
}
]
}
> db.post.aggregate([ {$lookup: {from:"vote", localField:"_id", foreignField:"post_id", as:"post_docs" } }, {$sort:{"post_docs.vote":1}} ]).pretty();
{
"_id" : ObjectId("5f42573349cf5c81666018f5"),
"title" : "hotel review",
"post_docs" : [
{
"_id" : ObjectId("5f42573349cf5c81666018f6"),
"post_id" : ObjectId("5f42573349cf5c81666018f5"),
"vote" : 22
}
]
}
{
"_id" : ObjectId("5f42581949cf5c81666018f7"),
"title" : "movie review",
"post_docs" : [
{
"_id" : ObjectId("5f42581949cf5c81666018f8"),
"post_id" : ObjectId("5f42581949cf5c81666018f7"),
"vote" : 99
}
]
}
>
Upvotes: 0
Reputation: 49985
Since you're trying to $sort
by an aggregated data from another collection, you need to use $lookup first in order to get total value from all related votes:
let posts = await Post.aggregate([
{
$lookup: {
from: "votes",
let: { post_votes: "$votes" },
pipeline: [
{ $match: { $expr: { $in: [ "$_id", "$$post_votes" ] } } },
{ $group: { _id: null, total: { $sum: "$value" } }
],
as: "votesTotalValue"
}
},
{ $unwind: "$votesTotalValue" },
{ $sort: { "votesTotalValue.total": -1 } }
])
Upvotes: 1
Reputation: 317
Inspired by this example on mongo's website.
db.sales.insertMany([
{ "_id" : 1, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("2"), "date" : ISODate("2014-03-01T08:00:00Z") },
{ "_id" : 2, "item" : "jkl", "price" : NumberDecimal("20"), "quantity" : NumberInt("1"), "date" : ISODate("2014-03-01T09:00:00Z") },
{ "_id" : 3, "item" : "xyz", "price" : NumberDecimal("5"), "quantity" : NumberInt( "10"), "date" : ISODate("2014-03-15T09:00:00Z") },
{ "_id" : 4, "item" : "xyz", "price" : NumberDecimal("5"), "quantity" : NumberInt("20") , "date" : ISODate("2014-04-04T11:21:39.736Z") },
{ "_id" : 5, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("10") , "date" : ISODate("2014-04-04T21:23:13.331Z") },
{ "_id" : 6, "item" : "def", "price" : NumberDecimal("7.5"), "quantity": NumberInt("5" ) , "date" : ISODate("2015-06-04T05:08:13Z") },
{ "_id" : 7, "item" : "def", "price" : NumberDecimal("7.5"), "quantity": NumberInt("10") , "date" : ISODate("2015-09-10T08:43:00Z") },
{ "_id" : 8, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("5" ) , "date" : ISODate("2016-02-06T20:20:13Z") },
])
Group By Item Quantity and Sorting Items according to Quantity
db.sales.aggregate( [
{
$group: {
_id: "$item",
count: { $sum:"$quantity" }
}
}
],
{$sort:{"_id.quantity":1}} )
Output
{
"_id" : "jkl",
"count" : NumberInt(1)
},
{
"_id" : "def",
"count" : NumberInt(15)
},
{
"_id" : "abc",
"count" : NumberInt(17)
},
{
"_id" : "xyz",
"count" : NumberInt(30)
}
Upvotes: 0