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
 
如有错误,请指正~
 
 
 
posted @ 2021-05-21 18:03  ellenxx  阅读(1141)  评论(0编辑  收藏  举报