【问题标题】:How do i sort by adding the values in mongoose using aggregation?我如何通过使用聚合在猫鼬中添加值来排序?
【发布时间】:2020-08-23 03:24:26
【问题描述】:

我有两个模型,发帖和投票。

发布架构

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

任何帮助将不胜感激。

谢谢!

【问题讨论】:

    标签: mongodb mongoose aggregation-framework


    【解决方案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

    【讨论】:

      【解决方案2】:

      灵感来自 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)
      }
      

      【讨论】:

      • OP 想要按需要从另一个集合中检索的值进行排序,因此 $group 不足以解决他的问题
      【解决方案3】:

      使用 $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
                      }
              ]
      }
      >
      

      【讨论】:

      • 为了清楚起见,聚合上述格式的代码。db.post.aggregate([ {$lookup: {from:"vote", localField:"_id", foreignField:"post_id", as:"post_docs" } }, {$sort:{"vote":-1}} ]).pretty();
      猜你喜欢
      • 2015-02-27
      • 2015-07-27
      • 2013-01-22
      • 1970-01-01
      • 2019-09-06
      • 2020-02-10
      • 2015-09-15
      • 1970-01-01
      • 2021-08-05
      相关资源
      最近更新 更多