mongoose aggregate $match does not match

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

Answers (1)

SuleymanSah
SuleymanSah

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 } ]

Playground

Upvotes: 2

Related Questions