Reputation: 47
I have an array of objects in which each object contains one array of action objects and one child object. I'd like to sum action points from one specific child id object.
When I test the sum at mongoplaygroundhttps://mongoplayground.net/ it works as expected but in the code, it is not so good. Please, someone, help me to point out what am I missing here?
Bellow It is my files:
array
[
{
"_id": "5e6990148c3e01001388b678",
"child": {
"image": "",
"_id": "5e695fe97bd186001526798d",
"name": "Mariana",
"gender": "female",
"dateBirth": "12/07/2010",
"createdAt": "2020-03-11T22:02:17.413Z",
"updatedAt": "2020-03-11T22:02:17.413Z",
"__v": 0
},
"actions": [
{
"_id": "5e6990148c3e01001388b679",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:27:48.747Z",
"updatedAt": "2020-03-12T01:27:48.747Z"
},
{
"_id": "5e6990148c3e01001388b67a",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:27:48.747Z",
"updatedAt": "2020-03-12T01:27:48.747Z"
},
{
"_id": "5e6990148c3e01001388b67b",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:27:48.747Z",
"updatedAt": "2020-03-12T01:27:48.747Z"
}
],
"createdAt": "2020-03-12T01:27:48.748Z",
"updatedAt": "2020-03-12T01:27:48.748Z",
"__v": 0
},
{
"_id": "5e6990578c3e01001388b67c",
"child": {
"image": "",
"_id": "5e644fecffc3150013eeafba",
"name": "Sheldon",
"gender": "male",
"dateBirth": "25/01/2014",
"createdAt": "2020-03-08T01:52:44.878Z",
"updatedAt": "2020-03-08T01:52:44.878Z",
"__v": 0
},
"actions": [
{
"_id": "5e6990578c3e01001388b67d",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:28:55.922Z",
"updatedAt": "2020-03-12T01:28:55.922Z"
},
{
"_id": "5e6990578c3e01001388b67e",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:28:55.922Z",
"updatedAt": "2020-03-12T01:28:55.922Z"
},
{
"_id": "5e6990578c3e01001388b67f",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:28:55.923Z",
"updatedAt": "2020-03-12T01:28:55.923Z"
},
{
"_id": "5e6990598c3e01001388b680",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:28:57.428Z",
"updatedAt": "2020-03-12T01:28:57.428Z"
},
{
"_id": "5e6990598c3e01001388b681",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:28:57.428Z",
"updatedAt": "2020-03-12T01:28:57.428Z"
},
{
"_id": "5e6990598c3e01001388b682",
"type": "extraNegativePoint",
"point": -10,
"pointType": "red",
"createdAt": "2020-03-12T01:28:57.428Z",
"updatedAt": "2020-03-12T01:28:57.428Z"
}
],
"createdAt": "2020-03-12T01:28:55.923Z",
"updatedAt": "2020-03-12T01:28:57.431Z",
"__v": 1
}
]
schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Promise = require('promise')
const actionSchema = new Schema({
type: {
type: String,
required: true
},
point: {
type: Number,
min: -1001,
max: 1001,
required: true
},
pointType: {
type: String,
required: true
},
goal:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Goals'
},
penalty: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Penalty'
},
award: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Award'
}
},{
timestamps: true
})
const realizationSchema = new Schema({
child: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Child'
},
actions: [actionSchema]
},
{
timestamps: true
});
realizationSchema.statics.fetchTotalPointsPerChild = function(childId) {
return new Promise((resolve, reject) => {
this.aggregate([
{
$match: {
"child._id": childId
}
},
{
$unwind: "$actions"
},
{
$group: {
_id: "$child._id",
totalPointsPerChild: {
$sum: "$actions.point"
}
}
}],
(err, result) => {
if (err) {
console.log("Error from search: fetchTotalPointsPerChild", err)
return reject(err);
}
resolve(result)
}
)
});
}
module.exports = mongoose.model('Realization', realizationSchema);
router
realizationRouter.route('/:childId/actions/totalPoints')
.get((req, res, next) => {
Realization.find()
.populate('child')
.populate('goals')
.populate('penalty')
.then(realization => {
if(realization) {
Realization.fetchTotalPointsPerChild(JSON.stringfy(req.params.childId))
.then(result => {
if(result){
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json(result);
}
})
.catch(err => next(err));
} else {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json(`There is no action to show from this child ${req.params.childId}`);
}
})
.catch(err => next(err));
});
module.exports = realizationRouter;
Upvotes: 3
Views: 179
Reputation: 17888
You are trying to aggregate on wrong sample documents, because based on the schema, action field is simply an ObjectId but not an object. It should be simply "child" : ObjectId("5e644fecffc3150013eeafba")
.
So your aggregation must be like this:
realizationSchema.statics.fetchTotalPointsPerChild = function(childId) {
return new Promise((resolve, reject) => {
this.aggregate(
[
{
$match: {
child: mongoose.Types.ObjectId(childId) //NOT "child._id": childId
}
},
{
$unwind: "$actions"
},
{
$group: {
_id: "$child", //NOT _id: "$child._id",
totalPointsPerChild: {
$sum: "$actions.point"
}
}
}
],
(err, result) => {
if (err) {
console.log("Error from search: fetchTotalPointsPerChild", err);
return reject(err);
}
console.log(result);
resolve(result);
}
);
});
};
console.log(result)
will display this in the console:
[ { _id: 5e644fecffc3150013eeafba, totalPointsPerChild: -60 } ]
Upvotes: 2