mongoose中聚合——aggregate的使用

aggregate()

语 法 \color{red}{语法}

db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION);

数 据 \color{red}{数据}

数据使用菜鸟教程的数据啦🤪🤪

/* 1 */
{
    "_id" : ObjectId("5e86e29788e64443e448dfc0"),
    "title" : "MongoDB Overview",
    "description" : "MongoDB is no sql database",
    "by_user" : "runoob.com",
    "url" : "http://www.runoob.com",
    "tags" : [ 
        "mongodb", 
        "database", 
        "NoSQL"
    ],
    "likes" : 100
}

/* 2 */
{
    "_id" : ObjectId("5e86e2ad88e64443e448dfd2"),
    "title" : "NoSQL Overview",
    "description" : "No sql database is very fast",
    "by_user" : "runoob.com",
    "url" : "http://www.runoob.com",
    "tags" : [ 
        "mongodb", 
        "database", 
        "NoSQL"
    ],
    "likes" : 10
}

/* 3 */
{
    "_id" : ObjectId("5e86e2bc88e64443e448dfd7"),
    "title" : "Neo4j Overview",
    "description" : "Neo4j is no sql database",
    "by_user" : "Neo4j",
    "url" : "http://www.neo4j.com",
    "tags" : [ 
        "neo4j", 
        "database", 
        "NoSQL"
    ],
    "likes" : 750
}

管 道 操 作 符 \color{red}{管道操作符}

操作符含义
$group将collection中的document分组,可用于统计结果
$match过滤数据,只输出符合结果的文档
$project修改输入文档的结构(例如重命名,增加、删除字段,创建结算结果等)
$sort将结果进行排序后输出
$limit限制管道输出的结果个数
$skip跳过制定数量的结果,并且返回剩下的结果
$unwind将数组类型的字段进行拆分

表 达 式 操 作 符 \color{red}{表达式操作符}

操作符含义实例
$sum计算总和,{$sum: 1}表示返回总和×1的值(即总和的数量),使用{$sum: '$制定字段'}也能直接获取制定字段的值的总和db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$sum : "$likes"}}}])
$avg平均值db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$avg : "$likes"}}}])
$min获取集合中所有文档对应值得最小值db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$min : "$likes"}}}])
$max获取集合中所有文档对应值得最大值db.collection.aggregate([{$group : {_id : "$by_user", content_sum : {$max : "$likes"}}}])
$push在结果文档中插入值到一个数组中db.collection.aggregate([{$group : {_id : "$by_user", url : {$push : "$url"}}}])
$addToSet在结果文档中插入值到一个数组中,但不创建副本db.collection.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first根据资源文档的排序获取第一个文档数据db.collection.aggregate([{$group : {_id : "$by_user", url : {$first : "$url"}}}])
$last根据资源文档的排序获取最后一个文档数据db.collection.aggregate([{$group : {_id : "$by_user", url : {$last : "$url"}}}])

具 体 例 子 \color{skyblue}{具体例子}

  • $group

    • 简单阐述

      //将document分组,用作统计结果
      db.collection.aggregate([       // aggregate方法接收的是一个数组
          {
              $group: {
              	// _id字段表示要基于哪个字段来进行分组(即制定字段值相同的为一组)
              	// $by_user表示要基于$by_user字段来进行分组
                  _id: '$by_user', 
                  // content_sum字段的值$sum: 1表示的是获取满足by_user字段相同的这一组的数量乘以后面给定的值(本例为1,那么就是同组的数量)。
                  content_sum: {$sum: 1}
              }
          }
      ])
      
    • 具体案例

      通过以上集合计算每个作者所写的文章数(通过字段by_user 字段对数据进行分组,并计算by_user字段相同值的总和),使用aggregate()计算结果如下:

      router.get('/getInfo',async(req, res)=>{
      let data=await Content.aggregate([
        {
          $group:{
            _id:'$by_user',
            content_sum:{$sum:1}
          }
        }
      ])
      res.json({data})
      })
      

      在这里插入图片描述

  • $match

    获取likes的值在50-200之间的数据:

    router.get('/getInfo', async (req, res) => {
      let data = await Content.aggregate([{
          $match: {
            likes: {
              $gt: 50,
              $lte: 200
            }
          }
        },
        {
          $group: {
            _id: '$_id',
            content_sum: {
              $sum: 1
            }
          }
        }
      ])
      res.json({
        data
      })
    })
    

    在这里插入图片描述

    从图中可以看出likes的值在50-200之间的数据只有1条,现在我们只知道这条数据的_id,如果想知道这条数据的具体信息时应该如何操作呢❓上面的表格中提到$project修改输入文档的结构(例如重命名,增加、删除字段,创建结算结果等),所以一起来看看吧👇👇👇

  • $project

    router.get('/getInfo', async (req, res) => {
      let data = await Content.aggregate([
        {
          $match: { likes: { $gt: 50, $lte: 200 } }
        },
        {
        //以下的值可以写$+字段,也可以使用0 和1来表示,若要显示字段则为1,否则为0
         
         //$project:{_id:'$_id',title:"$title",description:"$description",by_user:"$by_user",url:'$ulr',tags:'$tags',likes:'$likes'}
         $project:{_id:1,title:1,description:1,by_user:1,url:1,tags:1,likes:1}
        }
      ])
      res.json({
        data
      })
    })
    

    在这里插入图片描述

  • 以上3个操作符的综合使用

    如果想拿到所有likes>=10的document的by_user字段可以把管道搭配起来用:

    router.get('/getInfo', async (req, res) => {
      let data = await Content.aggregate([{
          $match: {
            likes: {
              $gt: 10
            }
          }
        },
        // 注意$project与$group的顺序,换位置后数据为空
        {
          $project: {
            _id: 0, //_id不显示
            by_user: 1 //by_user显示
          }
        },
        {
          $group: {
            _id: null,
            gameName: {
              $push: '$by_user'
            }
          }
        }
      ])
      res.json({
        data
      })
    })
    

    在这里插入图片描述

  • $sort

    • 根据likes进行降序排序

      router.get('/getInfo', async (req, res) => {
        let data = await Content.aggregate([
          {
            $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 }
          },
          {
            $sort: { likes: -1 }
          },
        ])
        res.json({
          data
        })
      })
      

      在这里插入图片描述

    • 根据likes进行升序排序

      router.get('/getInfo', async (req, res) => {
        let data = await Content.aggregate([
          {
            $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 }
          },
          {
            $sort: { likes: 1 }
          },
        ])
        res.json({
          data
        })
      })
      

      在这里插入图片描述

  • $limit and $skip

    router.get('/getInfo', async (req, res) => {
      let data = await Content.aggregate([
        {
          $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 }
        },
        {
          $sort: { likes: 1 }
        },
        {
          $skip:1
        },
        {
          $limit:1
        }
      ]);
      
      res.json({
        data
      })
    })
    

    在这里插入图片描述

  • $unwind

    $unwind管道以document中的数组类型的字段进行拆分,每条包含数组中的一个值。

    比如拆分likes:10这条数据,先来看看整体数据信息吧:

    {
        "_id" : ObjectId("5e86e2ad88e64443e448dfd2"),
        "title" : "NoSQL Overview",
        "description" : "No sql database is very fast",
        "by_user" : "runoob.com",
        "url" : "http://www.runoob.com",
        "tags" : [ 
            "mongodb", 
            "database", 
            "NoSQL"
        ],
        "likes" : 10
    }
    

    tags数组中有3条数据,所以拆分后会显示3条数据,看看具体实现吧:

    router.get('/getInfo', async (req, res) => {
      let data = await Content.aggregate([
        {
          $match: {
            likes: 10
          }
        },
        {
          $unwind:'$tags'
        },
        {
          $project: { _id: 1, by_user: 1, title: 1, title: 1, description: 1, url: 1, tags: 1, likes: 1 }
        },
      ])
      res.json({
        data
      })
    })
    

    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值