• mongoose聚合——$project


    $project:修改输入文档的结构,可以用来增加、删除、修改域,或创建文档,也可用于创建计算结果以及嵌套文档。 

    数据表

    //Articles
    [{
    "_id":"5eb4cb0dcf4cc329300df1de","title":"dfgtest文章",
    "publishDate":"2020-05-22T00:00:00.000Z", "content":"<p>ABCdefg</p>",
    "val":1, "setting":{"isTop":true}, }, { "_id":"5eb4ec52d3a5c90fecd0e43e","title":"托尔斯泰2",
    "val":1,
    "publishDate":"2020-05-03T00:00:00.000Z", "content":"<p>ABCD</p>", "setting":{"isTop":false}, }]
    //Users
    [{
    "_id":"5eae1e25c938a74ec0e5fb7a", "username":"mmtest", "email":"10001001@test.com", }, { "_id":"5eb12980c7bb9821ac08fcf2", "username":"zhangsan", "email":"10001002@test.com" }]        

    代码

    这里的代码只显示query部分,文末附上完整代码。

    Model.aggregate([
          ...query
    ])
    
    //Model表示Users或Articles

    1. 更改字段名

    代码:将_id的字段名修改为id,username的字段名修改为name。

    const query = [
        {
          $project: {
            _id: 0, // 默认情况下_id是包含的,将_id设置为0|false,则选择不包含_id,其他字段也可以这样选择是否显示。
            id: '$_id',
            name: '$username'
          }
        }
     ]

    原始数据与结果:

    [{
    "_id":"5eae1e25c938a74ec0e5fb7a",
    "username":"mmtest",
    "email":"10001001@test.com",
    },
    ...]
    ---聚合后---

    [{ id: 5eae1e25c938a74ec0e5fb7a, name: 'mmtest' }, ...]

    2.对数据中对象进行操作

    代码:提取setting对象中的isTop;创建sub对象

    const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            isTop: '$setting.isTop',
            sub: {
              date: '$publishDate'
            }
          }
        }
    ]

    原始数据与结果:

    
    
    [{
    "_id":"5eb4cb0dcf4cc329300df1de","title":"dfgtest文章",
    "publishDate":"2020-05-22T00:00:00.000Z", "content":"<p>ABCdefg</p>","val":1, "setting":{"isTop":true}, },

    ...]
    ---聚合后---

    [ { title:
    'dfgtest文章', isTop: 'true', sub: { date: 2020-05-22T00:00:00.000Z } },
    ... ]

    3.四则运算

    代码:对val进行加、减、乘、除、模2

    加法($add)、减法($subtract)、乘法($multiply)、除法($divide)、求模($mod)
    const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            add: { $add: ['$val', 2] },
            multiply: { $multiply: ['$val', 2] },
            subtract: { $subtract: ['$val', 2] },
            divide: { $divide: ['$val', 2] },
            mod: { $mod: ['$val', 2] }
          }
        }
      ]

     原始数据与结果:

    [{
    "_id":"5eb4cb0dcf4cc329300df1de","title":"dfgtest文章",
    "publishDate":"2020-05-22T00:00:00.000Z",
    "content":"<p>ABCdefg</p>",
    "val":1,
    "setting":{"isTop":true},
    },
    ...]
    ---聚合后---
    [
      {
       title: 'dfgtest文章',
        add: 3,
        multiply: 2,
        subtract: -1,
        divide: 0.5,
        mod: 1
        },
    ...
    ]

    4.关系运算

    代码:对val进行关系运算

    (1)将Boolean值转化为数字("$cmp"),cmp:{$cmp:['$setting.isTop',false]},如果setting.isTop=false,那么cmp为0;如果setting.isTop=true,那么cmp为1,如果setting.isTop不是Boolean类型或为null,cmp为-1。
    (2)等于("$eq")、大于("$gt")、大于等于("$gte")、小于("$lt")、小于等于("$lte")、不等于("$ne")这些返回值都是 boolean 值类型的,如果没有val值,那么会默认val=0。
    (3)判断 null ("$ifNull"),ifNull:{$ifNull:['$val',etc]},如果val上不为Null,则ifNull就是val的值;如果val为Null,那么ifNull就是etc的值。
     
     const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            cmp: { $cmp: ['$setting.isTop', false] },
            eq: { $eq: ['$val', 2] },
            gt: { $gt: ['$val', 2] },
            gte: { $gte: ['$val', 2] },
            lt: { $lt: ['$val', 0] },
            lte: { $lte: ['$val', 2] },
            ne: { $ne: ['$val', 2] },
            ifNull: { $ifNull: ['$val', 2] }
          }
        }
      ]

     原始数据与结果:

    [{
    "_id":"5eb4cb0dcf4cc329300df1de","title":"dfgtest文章",
    "publishDate":"2020-05-22T00:00:00.000Z",
    "content":"<p>ABCdefg</p>",
    "val":1,
    "setting":{"isTop":true},
    },
    {
    "_id":"5eb4ec52d3a5c90fecd0e43e","title":"托尔斯泰2",
    "publishDate":"2020-05-03T00:00:00.000Z", "content":"<p>ABCD</p>", "setting":{"isTop":false}, }]

    ---聚合后---
    [
      

    {
    title: 'dfgtest文章',
    cmp: 1,
    eq: false,
    gt: false,
    gte: false,
    lt: false,
    lte: true,
    ne: true,
    ifNull: 1
    },
    {
    title: '托尔斯泰2',
    cmp: 0,
    eq: false,
    gt: false,
    gte: false,
    lt: true,
    lte: true,
    ne: true,
    ifNull: 2
    }

    ]
     

    5.字符串操作

     代码:
    连接("$concat")、截取("$substr")、转小写("$toLower")
    const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            concat1: { $concat: ['$title', '+1+1'] },
            concat2: { $concat: ['$title', '$content'] },
            substr:{ $substr: ['$title', 0,3] },
            toLower:{ $toLower: '$content'},
          }
        }
    ]

      原始数据与结果:

    [{
    "_id":"5eb4cb0dcf4cc329300df1de","title":"dfgtest文章",
    "publishDate":"2020-05-22T00:00:00.000Z",
    "content":"<p>ABCdefg</p>",
    "val":1,
    "setting":{"isTop":true},
    },
    ...]
    ---聚合后---
    [
      {
        title: 'dfgtest文章',
        concat1: 'dfgtest文章+1+1',
        concat2: 'dfgtest文章<p>ABCdefg</p>',
        substr: 'dfg',
        toLower: '<p>abcdefg</p>'
        },
    ...
    ]

    6.日期

    代码:

    $year年份,$month月份,当月$dayOfMonth,$dayOfYear当年过了多少天
    const query = [
          {
            $project: {
              _id: 0,
              title: '$title',
              date:{
                year:{$year:'$publishDate'},
                month:{$month:'$publishDate'},
                dayOfMonth:{$dayOfMonth:'$publishDate'},
                dayOfYear:{$dayOfYear:'$publishDate'}
                }
              }
            }
      ]

       原始数据与结果:

    [{
    "_id":"5eb4cb0dcf4cc329300df1de","title":"dfgtest文章",
    "publishDate":"2020-05-22T00:00:00.000Z",
    "content":"<p>ABCdefg</p>",
    "val":1,
    "setting":{"isTop":true},
    },
    ...]
    ---聚合后---
    [
      {
        title: 'dfgtest文章',
        date: { year: 2020, month: 5, dayOfYear: 143 }
        },
    ...
    ]
     
     

    完整代码

    const Articles = require('../../model/articles');
    const Users = require('../../model/users');
    
    //使用$project修改输入文档的结构,可以用来增加、删除、修改域,或创建文档,也可用于创建计算结果以及嵌套文档。
    
    //-----------------------------1---------------------------
    /**
     * 结果user只输出id,name
     */
    async function project1() {
      const query = [
        {
          $project: {
            _id: 0, // 默认情况下_id是包含的,将_id设置为0,则选择不包含_id
            id: '$_id',
            name: '$username'
          }
        }
      ]
    
      await usersAggregate(query);
    }
    
    //-----------------------------2---------------------------
    //在mongoose中,使用以下代码会报错
    /* 
    async function project2(){
      const query='username email -_id';
      await usersAggregate(query);
    }
    */
    
    //-----------------------------3---------------------------
    /**
     * 对数据中对象进行操作
     */
    async function project3() {
      const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            isTop: '$setting.isTop',
            val: '$val',
            sub: {
              date: '$publishDate'
            }
          }
        }
      ]
    
      await articlesAggregate(query);
    }
    
    
    //-----------------------------4---------------------------
    //加法($add)、减法($subtract)、乘法($multiply)、除法($divide)、求模($mod)
    /**
     * 对数据val中进行四则运算操作,val=1
     */
    async function project4() {
      const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            add: { $add: ['$val', 2] },
            multiply: { $multiply: ['$val', 2] },
            subtract: { $subtract: ['$val', 2] },
            divide: { $divide: ['$val', 2] },
            mod: { $mod: ['$val', 2] }
          }
        }
      ]
    
      await articlesAggregate(query);
    }
    
    
    //-----------------------------5---------------------------
    //关系运算:将Boolean值转化为数字("$cmp"),cmp:{$cmp:['$setting.isTop',false]},如果setting.isTop=false,那么cmp为0;如果setting.isTop=true,那么cmp为1,如果setting.isTop不是Boolean类型或为null,cmp为-1
    //等于("$eq")、大于("$gt")、大于等于("$gte")、小于("$lt")、小于等于("$lte")、不等于("$ne")、这些返回值都是 boolean 值类型的。
    //判断 null ("$ifNull"),ifNull:{$ifNull:['$val',etc]},如果val上不为Null,则ifNull就是val的值;如果val为Null,那么ifNull就是etc的值。
    
    /**
     * 关系运算
     */
    async function project5() {
      const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            cmp: { $cmp: ['$setting.isTop', false] },
            eq: { $eq: ['$val', 2] },
            gt: { $gt: ['$val', 2] },
            gte: { $gte: ['$val', 2] },
            lt: { $lt: ['$val', 0] },
            lte: { $lte: ['$val', 2] },
            ne: { $ne: ['$val', 2] },
            ifNull: { $ifNull: ['$val', 2] }
          }
        }
      ]
    
      await articlesAggregate(query);
    }
    
    
    //-----------------------------6---------------------------
    //字符串操作
    //连接("$concat")、截取("$substr")、转小写("$toLower")
    /**
     * 字符串操作
     */
    async function project6() {
      const query = [
        {
          $project: {
            _id: 0,
            title: '$title',
            concat1: { $concat: ['$title', '+1+1'] },
            concat2: { $concat: ['$title', '$content'] },
            substr:{ $substr: ['$title', 0,3] },
            toLower:{ $toLower: '$content'},
          }
        }
      ]
    
      await articlesAggregate(query);
    }
    
    //-----------------------------7---------------------------
    //日期:$year年份,$month月份,当月$dayOfMonth,$dayOfYear当年过了多少天
    /**
     * 日期
     */
      async function project7() {
        const query = [
          {
            $project: {
              _id: 0,
              title: '$title',
              date:{
                year:{$year:'$publishDate'},
                month:{$month:'$publishDate'},
                dayOfMonth:{$dayOfMonth:'$publishDate'},
                dayOfYear:{$dayOfYear:'$publishDate'}
                }
              }
            }
        ]
      
        await articlesAggregate(query);
      }
    
    
    /**
     * users聚合结果模板
     * @param {Array} query 聚合的参数
     */
    async function usersAggregate(query) {
      try {
        const result = await Users.aggregate([
          ...query
        ])
    
        console.log(result);
    
      } catch (err) {
        console.log(query)
        console.log("聚合失败...", err)
      }
    }
    
    /**
     * articles聚合结果模板
     * @param {Array} query 聚合的参数
     */
    async function articlesAggregate(query) {
      try {
        const result = await Articles.aggregate([
          ...query
        ])
    
        console.log(result);
    
      } catch (err) {
        console.log(query)
        console.log("聚合失败...", err)
      }
    }
    
    function main() {
      // project2();
      // project3();
      // project4();
      // project5();
      project6();
      // project7();
    }
    
    main();
     参考致谢:
    https://blog.csdn.net/github_38589282/article/details/76735688
    https://blog.csdn.net/qq_18948359/article/details/88777314
    https://www.runoob.com/mongodb/mongodb-aggregate.html
     
    如有错误,请指正~
     
     
     
  • 相关阅读:
    T3java核心API基础类
    java字符编码
    Servlet 1
    T2java面向对象
    T1java语言基础
    Mac OS mysql数据库安装与初始化
    java多线程中注入Spring对象问题
    T4java核心API集合类
    The first day Teddy
    Spring第二节 注入依赖
  • 原文地址:https://www.cnblogs.com/ellen-mylife/p/14794284.html
Copyright © 2020-2023  润新知