$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
如有錯誤,請指正~
