如何使用聚合在猫鼬中添加值进行排序?

时间:2020-08-23 03:24:26

标签: mongodb mongoose aggregation-framework

我有两种模式,张贴和投票。

发布架构

title:{
    type: String,
    required: true,
},
description:{
    type: String,
    required: true,
},
votes: [
    {
        type: Schema.Types.ObjectId,
        ref: 'Vote'
    }
],

投票架构

const voteSchema = new Schema({
    post:{
        type: Schema.Types.ObjectId,
        ref: 'Post',
    },
    value:{
        type: Number,
        required: true,
    },
});

我正在尝试按照分组投票的最高价值对帖子进行排序。

也许是这样吗?

var posts = Post.aggregate([{$sort: { $group: votes: {$sum: value} }}

任何帮助将不胜感激。

谢谢!

3 个答案:

答案 0 :(得分:1)

由于您要尝试$sort来自另一个集合的汇总数据,因此需要首先使用$lookup才能从所有相关投票中获得总价值:

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 } }
])

Mongo Playground

答案 1 :(得分:0)

受到mongo网站上这个example的启发。

 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") },
])

按项目数量分组并按数量对项目进行排序

db.sales.aggregate( [
{
$group: {
   _id: "$item",
   count: { $sum:"$quantity" }
  }
 }
],
{$sort:{"_id.quantity":1}} )

输出

{ 
"_id" : "jkl", 
"count" : NumberInt(1)
},
{ 
"_id" : "def", 
"count" : NumberInt(15)
},
{ 
"_id" : "abc", 
"count" : NumberInt(17)
},
{ 
"_id" : "xyz", 
"count" : NumberInt(30)
}

答案 2 :(得分:0)

代码示例,用于通过$ lookup和排序从两个集合中检索数据

// 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
                }
        ]
}
>