简体   繁体   English

Mongoose:按对象 id 分组并推入一个数组,按 createdAt 排序,填充所有对象并对其进行分页

[英]Mongoose: Group by Object id and push in one array, sort by createdAt, populate all objects and paginate it

This is an example of getList of Arrivals by 10 items per page:这是按每页 10 个项目获取到达列表的示例:

router.get('/arrivals', isAuthenticated, async (request, response, next) => {
  jsonPreProcessor.response = response;

  const resPerPage = 10;
  const page = request.query.page || 1;

  Arrival.find({})
    .populate({
      path: 'product',
      populate: {
        path: 'type'
      }
    })
    .select('-__v')
    .skip((resPerPage * page) - resPerPage)
    .limit(resPerPage).then(arrivals => {
      Arrival.countDocuments({}).then(numberOfResults => {
        return jsonPreProcessor.paginate(arrivals, page, Math.ceil(numberOfResults / resPerPage), numberOfResults);
      }).catch(error => {
        return jsonPreProcessor.error(error.message);
      });
    }).catch(error => {
      return jsonPreProcessor.error(error.message);
    });
});

And this is an output:这是一个输出:

{
  "time": "2020-01-16T10:11:22.588Z",
  "message": "success",
  "success": true,
  "data": {
    "list": [
      {
        "quantity": 1,
        "discount": 0,
        "_id": "5e0db80a37dd4437b4329960",
        "product": {
          "_id": "5e0cecaaa9a5cc2c7c62e379",
          "title": "Ортопедический",
          "type": {
            "_id": "5ddcbc4685e53838dc564a44",
            "title": "fsdkjhfs",
            "createdAt": "2019-11-26T05:46:46.797Z",
            "updatedAt": "2019-11-26T05:46:46.797Z",
            "alt": "fsdkjhfs",
            "__v": 0
          },
          ...
          "mode": "simple",
          "createdAt": "2020-01-01T19:02:02.840Z",
          "updatedAt": "2020-01-01T19:02:02.840Z",
          "alt": "ortopedicheskij",
          "__v": 0
        },
        ...
        "sellPrice": 6,
        "minSellPrice": 0,
        "createdAt": "2020-01-02T09:29:46.688Z",
        "updatedAt": "2020-01-13T09:30:26.126Z"
      },
      ... // And other 9 items
    ],
    "currentPage": 1,
    "pages": 2,
    "numberOfResults": 16,
    "incompleteResults": true
  },
  "type": null
}

All those are arrivals, and as you see arrivals have product.所有这些都是到货,正如你所见,到货有产品。 Some arrivals can have same product (by id)一些到达可以有相同的产品(通过 id)
My problem is to group arrivals which have same product.我的问题是将具有相同产品的到达者分组。 (sorted by first item of arrivals array) populate all objects.. and paginate. (按到达数组的第一项排序)填充所有对象......并分页。 I use aggregate, and unfortunately I don't have any idea how to use it (first of all aggregate's output is random) with pagination and of course output is not what I need.我使用聚合,不幸的是我不知道如何使用它(首先聚合的输出是随机的)和分页,当然输出不是我需要的。 I used this link as solving of my problem.我用这个链接来解决我的问题。

router.get('/arrivalls', isAuthenticated, async (request, response, next) => {
  jsonPreProcessor.response = response;

  Arrival.aggregate(
    [
      // This is not working (may be it's not working in array)
      // {
      //   "$sort": {
      //     "createdAt": 1
      //   }
      // },
      {
        "$group": {
          "_id": "$product",
          "arrivals": {
            "$push": "$$ROOT"
          }
        }
      },
      // {
      //   "$lookup": {
      //     "from": "arrivals",
      //     "localField": "product",
      //     "foreignField": "_id",
      //     "as": "product"
      //   }
      // },
      // {
      //   "$unwind": {
      //     "path": "$arrivals"
      //   }
      // }
    ]
  ).then(arrivals => {
      // console.log(arrivals);
      return jsonPreProcessor.success(arrivals);
    }).catch(error => {
      return jsonPreProcessor.error(error.message);
    });
});

Output should be like:输出应该是这样的:

  "data": {
    "list": [
    {
      "_id": "5e1d5dba611485397cfb0386",
      "arrivals": [
        {
          "_id": "5e1d5e26611485397cfb0387",
          "quantity": 6,
          "discount": 0,
          "product": {
            "_id": "5e1d5dba611485397cfb0386",
            ... // etc
          },
          "sellPrice": 5000,
          "minSellPrice": 4500,
          "createdAt": "2020-01-14T06:22:30.366Z",
          "updatedAt": "2020-01-14T09:14:13.824Z",
          "__v": 0
        },
        {
          "_id": "5e1ff4d15d059430e8405f94",
          "quantity": 2,
          "discount": 0,
          "product": {
            "_id": "5e1d5dba611485397cfb0386",
            ... // etc
          },
          "sellPrice": 7000,
          "minSellPrice": 6000,
          "comment": "",
          "createdAt": "2020-01-16T05:29:53.907Z",
          "updatedAt": "2020-01-16T05:29:53.907Z",
          "__v": 0
        }
      ]
    },
    {
      "_id": "5e1d84884d387d2334a7e9d9",
      "arrivals": [
        {
          // etc...
        }
      ]
    }
  ],
  "currentPage": 1,
  "pages": 2,
  "numberOfResults": 16,
  "incompleteResults": true
},
"type": null

} }

I solved my problem.. And here is grouping, sorting, populating and paginating of list.我解决了我的问题..这里是列表的分组、排序、填充和分页。

  const resPerPage = 10;
  const page = request.query.page || 1;

  Arrival.aggregate(
    [
      {
        $lookup: {
          from: 'products',
          localField: 'product',
          foreignField: '_id',
          as: 'product'
        }
      },
      {
        $unwind: {
          path: "$product",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $lookup: {
          from: 'branchdans',
          localField: 'branch',
          foreignField: '_id',
          as: 'branch'
        }
      },
      {
        $unwind: {
          path: "$branch",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $lookup: {
          from: 'colors',
          localField: 'color',
          foreignField: '_id',
          as: 'color'
        }
      },
      {
        $unwind: {
          path: "$color",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $lookup: {
          from: 'types',
          localField: 'product.type',
          foreignField: '_id',
          as: 'product.type'
        }
      },
      {
        $unwind: {
          path: "$product.type",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $lookup: {
          from: 'subcategories',
          localField: 'product.subcategory',
          foreignField: '_id',
          as: 'product.subcategory'
        }
      },
      {
        $unwind: {
          path: "$product.subcategory",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $lookup: {
          from: 'categories',
          localField: 'product.subcategory.category',
          foreignField: '_id',
          as: 'product.subcategory.category'
        }
      },
      {
        $unwind: {
          path: "$product.subcategory.category",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $lookup: {
          from: 'countries',
          localField: 'product.country',
          foreignField: '_id',
          as: 'product.country'
        }
      },
      {
        $unwind: {
          path: "$product.country",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $lookup: {
          from: 'manufacturers',
          localField: 'product.manufacturer',
          foreignField: '_id',
          as: 'product.manufacturer'
        }
      },
      {
        $unwind: {
          path: "$product.manufacturer",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $group: {
          "_id": "$product._id",
          "sizes": {
            "$first": "$product.sizes"
          },
          "title": {
            "$first": "$product.title"
          },
          "type": {
            "$first": "$product.type"
          },
          "subcategory": {
            "$first": "$product.subcategory"
          },
          "country": {
            "$first": "$product.country"
          },
          "manufacturer": {
            "$first": "$product.manufacturer"
          },
          "description": {
            "$first": "$product.description"
          },
          "comment": {
            "$first": "$product.comment"
          },
          "mode": {
            "$first": "$product.mode"
          },
          "createdAt": {
            "$first": "$product.createdAt"
          },
          "updatedAt": {
            "$first": "$product.updatedAt"
          },
          "alt": {
            "$first": "$product.alt"
          },
          arrivals: {
            $push: "$$ROOT"
          },
          "date": {
            $last: "$createdAt"
          }
        },
      },
      {
        $unset: "arrivals.product"
      },
      {
        $sort: {
          "date": 1
        }
      },
      {
        $skip: (resPerPage * page) - resPerPage
      },
      {
        $limit: resPerPage
      }
    ]
  ).then(arrivals => {

      Arrival.aggregate([
        {
          $group: {
            "_id": "$product",
            arrivals: {
              $push: "$$ROOT"
            },
            "date": {
              "$last": "$createdAt"
            }
          },
        },
        {
          $sort: {
            "date": 1
          }
        },
        {
          $count: "numberOfResults"
        }
      ]).then(countArrivals => {
        if(countArrivals.length === 0){
          return jsonPreProcessor.error('Ошибка при высчитывании прибытий товаров');
        }
        // Todo make more practise
        return jsonPreProcessor.paginate(arrivals, page, Math.ceil(countArrivals[0].numberOfResults / resPerPage), countArrivals[0].numberOfResults);
      }).catch(error => {
        return jsonPreProcessor.error(error.message);
      });

      // return jsonPreProcessor.success(arrivals);
    }).catch(error => {
      return jsonPreProcessor.error(error.message);
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM