aravindnc / mongoose-aggregate-paginate-v2

A cursor based custom aggregate pagination library for Mongoose with customizable labels.
MIT License
131 stars 23 forks source link

$lookup and $project not working #29

Closed albertyou2 closed 2 years ago

albertyou2 commented 3 years ago

nodejs : v11.15.0 mongoose : v5.5.2 mongodb server : 4.0.3

hi @aravindnc : I was try to use $lookup and $project with mongoose-aggregate-paginate-v2. This is my query code :

const options = {
    page  : pageNum,
    limit : pageLimit,
    sort  : {created :-1},
 };
let actsRes = await app.model.StuActivate.aggregatePaginate([
      { $match:{
        studentId : body.studentId,
      }},
      {$lookup: {
        from: 'rolemaps',
        localField: 'creatorId',
        foreignField: '_id',
        as:'roleInfo'
      }},
      {$project: {
        roleInfo    : {$arrayElemAt: ['$roleInfo', 0]},
        created     : true,
        itemType    : 'act',
        scale       :  true,
        title       : 1,
        achievement : 1,
      }},
      {$project: {
        teacherName   : '$roleInfo.name',
        teacherAvatar : '$roleInfo.avatar', 
        created     :  true,
        itemType    : 'act',
        scale       : 1,
        title       : 1,
        achievement : 1,
      }},
      {$sort : {created :-1}}
    ],options);

   Both $lookup and $project are not working . The result date looked like this : 
  {
    "_id":"5fa0f5c1a67787643befcb97",
    "scale":[
    "MCE",
    "PD"
    ],
    "modifies":[
    ],
    "schoolId":"5f633bf134e7a32450b88090",
    "studentId":"5f656c5cf81bbf5b757bd8f9",
    "startDate":"2020-10-01T00:00:00.000Z",
    "endDate":"2020-10-10T00:00:00.000Z",
    "type":"outReward",
    "title":"test title",
    "achievement":"ontents here",
    "hours":10,
    "date":"2020-10-01",
    "yearMonth":"2020-10",
    "yearWeek":"2020-40",
    "creatorId":"5f633bf134e7a32450b88091",
    "created":"2020-11-03T06:16:33.846Z",
    "updated":"2020-11-03T06:16:33.846Z"
  },

  But when I use the native aggreagetion of mongoose , here is my code ::
  let actsRes = await app.model.StuActivate.aggregate([
      { $match:{
        studentId : body.studentId,
      }},
      {$lookup: {
        from: 'rolemaps',
        localField: 'creatorId',
        foreignField: '_id',
        as:'roleInfo'
      }},
      {$project: {
        roleInfo    : {$arrayElemAt: ['$roleInfo', 0]},
        created     : true,
        itemType    : 'act',
        scale       :  true,
        title       : 1,
        achievement : 1,
      }},
      {$project: {
        teacherName   : '$roleInfo.name',
        teacherAvatar : '$roleInfo.avatar', 
        created     :  true,
        itemType    : 'act',
        scale       : 1,
        title       : 1,
        achievement : 1,
      }},
      {$sort : {created :-1}}
    ]);

 It can return the correct result:
  {
    "_id":"5fa0f5c1a67787643befcb97",
    "scale":[
      "MCE",
      "PD"
    ],
    "title":"test title",
    "achievement":"contents here",
    "created":"2020-11-03T06:16:33.846Z",
    "teacherName":"Mike",
    "teacherAvatar":"http://public.edu.brmind.cn/2020-10-19/5184_1603100167198_avatar.jpg",
    "itemType":"act"
 },
Is there something important I am missing ?Thank you
racingcow commented 3 years ago

For me, I had to use the model to create an aggregate first, then pass that to aggregatePaginate, like this...

// ...
let actsRes = await app.model.StuActivate.aggregatePaginate(app.model.StuActivate.aggregate([
// ...

The examples in the readme show this as well, but at first I didn't look at it carefully enough, and missed the extra call to myModel.aggregate();.

var myModel = require('/models/samplemodel');

const options = {
    page: 1,
    limit: 10
};

var myAggregate = myModel.aggregate();
myModel.aggregatePaginate(myAggregate, options).then(function(results){
    console.log(results);
}).catch(function(err){
    console.log(err);
})
kelechithefuture commented 3 years ago

I am actually having this issue. I followed the documentation. Here's my piece of code:

const postData = 
            await Posts.aggregate([
                { $match: { postingType: "posted" } }, 
                {
                    $lookup: {
                      from: 'users',
                      localField: 'authorID',
                      foreignField: '_id',
                      as: 'user',
                    },
                },
                { $unwind: { path: '$user', preserveNullAndEmptyArrays: true } },
                {
                    $addFields:{ "user": "$user" }
                }
            ])

        const options = {
            page: page,
            limit: 10
        };

        Posts
            .aggregatePaginate(postData, options)
            .then(function (results) {
                console.log(results);
                res.status(200).json(results);
            })
            .catch(function (err) {
                console.log(err);
            });

My result is without the "user" object. Here is an object of the whole array of objects:

{
      _id: 609589cec6ee911020e1c24e,
      tags: [Array],
      status: 'active',
      authorID: 6079a8cdfc75353a23688cd7,
     ...
    }

But when I console postData which I feed into aggregatePaginate(), I get the user object:

{
    ...
    user: {
      _id: 6079a8cdfc75353a23688cd7,
      type: 'user',
      ...
  },

I used the $addFields stage to see if it would preserve the "user" object, but NO

kelechithefuture commented 3 years ago

I am actually having this issue. I followed the documentation. Here's my piece of code:

const postData = 
            await Posts.aggregate([
              { $match: { postingType: "posted" } }, 
              {
                  $lookup: {
                    from: 'users',
                    localField: 'authorID',
                    foreignField: '_id',
                    as: 'user',
                  },
              },
              { $unwind: { path: '$user', preserveNullAndEmptyArrays: true } },
              {
                  $addFields:{ "user": "$user" }
              }
          ])

      const options = {
          page: page,
          limit: 10
      };

      Posts
          .aggregatePaginate(postData, options)
          .then(function (results) {
              console.log(results);
              res.status(200).json(results);
          })
          .catch(function (err) {
              console.log(err);
          });

My result is without the "user" object. Here is an object of the whole array of objects:

{
      _id: 609589cec6ee911020e1c24e,
      tags: [Array],
      status: 'active',
      authorID: 6079a8cdfc75353a23688cd7,
     ...
    }

But when I console postData which I feed into aggregatePaginate(), I get the user object:

{
    ...
    user: {
      _id: 6079a8cdfc75353a23688cd7,
      type: 'user',
      ...
  },

I used the $addFields stage to see if it would preserve the "user" object, but NO

I just discovered that the problem was the await placed right before the aggregate():

**await** Posts.aggregate([])

After I removed the await, I got the required response (with the "user" object)

ashfaqnisar commented 2 years ago

@albertyou2, @aravindnc Can you close this issue as the bug is resolved.

aravindnc commented 2 years ago

Thanks.

devjsrana commented 1 year ago

I am actually having this issue. I followed the documentation. Here's my piece of code:

const postData = 
            await Posts.aggregate([
                { $match: { postingType: "posted" } }, 
                {
                    $lookup: {
                      from: 'users',
                      localField: 'authorID',
                      foreignField: '_id',
                      as: 'user',
                    },
                },
                { $unwind: { path: '$user', preserveNullAndEmptyArrays: true } },
                {
                    $addFields:{ "user": "$user" }
                }
            ])

        const options = {
            page: page,
            limit: 10
        };

        Posts
            .aggregatePaginate(postData, options)
            .then(function (results) {
                console.log(results);
                res.status(200).json(results);
            })
            .catch(function (err) {
                console.log(err);
            });

My result is without the "user" object. Here is an object of the whole array of objects:

{
      _id: 609589cec6ee911020e1c24e,
      tags: [Array],
      status: 'active',
      authorID: 6079a8cdfc75353a23688cd7,
     ...
    }

But when I console postData which I feed into aggregatePaginate(), I get the user object:

{
    ...
    user: {
      _id: 6079a8cdfc75353a23688cd7,
      type: 'user',
      ...
  },

I used the $addFields stage to see if it would preserve the "user" object, but NO

I just discovered that the problem was the await placed right before the aggregate():

**await** Posts.aggregate([])

After I removed the await, I got the required response (with the "user" object)

It really works thanks