首页 > 解决方案 > mongoDB, mongoose - 聚合对象数组

问题描述

我有 3 个要汇总的集合。

第一个是颜色集合

{
    {
        _id: 1,   <- mongoose objectId
        name: red
    },
    {
        _id: 2,   <- mongoose objectId
        name: green
    }
}

二是产品

{
    {
        _id: Id777, <- mongoose objectId
        productName: test prod 777
    },
    {
        _id: Id888, <- mongoose objectId
        productName: test prod 888
    }
}

第三个它移动集合

{
    ....other fields here
    items: [
        {
            _id: an mongoose id,
            itemId: Id777 <- in products collection,
            itemColor: 1 <- id in colors collection,
            coutn: 7,
            ....other fields
        },
        {
            _id: an mongoose id,
            itemId: Id888 <- in products collection,
            itemColor: 2 <- id in colors collection
            cout: 10
            ....other fields
        }
    ]
}

我需要有这样的输出:

{
    ////information from collection
    items: [
        {
            itemId: test prod 777, itemColor: red, count: 7
        },
        {
            itemId: test prod 888, itemColor: green, count: 10
        }
    ]
}

我的代码是:

      const moves = await ProductMoves.aggregate([
            { $match: query }, // this is my query

            {
                $lookup: {
                    from: 'products',
                    localField: 'items.itemId',
                    foreignField: '_id',
                    as: 'productName'
                }
            },
            {
                $unwind: { path: "$productName" , preserveNullAndEmptyArrays: true }
            },

            {
                $lookup: {
                    from: 'colors',
                    localField: 'items.itemColor',
                    foreignField: '_id',
                    as: 'cName'
                }
            },
            {
                $unwind: { path: "$cName" , preserveNullAndEmptyArrays: true }
            },

            {
                $addFields: {
                    mItems: {
                        prName: "$productName.productName",
                        prColor: "$cName.colorName"
                    },
                    productName: 0,
                    cName: 0
                }
            }

        ])
            .sort({addedDate: -1})
            .skip(+req.query.offset)
            .limit(+req.query.limit)

但它只返回对象数组中的 1 个元素。可能我需要类似 for 循环的东西,但我做不到。

感谢您的回复,祝您有美好的一天!

标签: mongodbmongooseaggregation-framework

解决方案


  • $unwind解构items数组
  • $lookupproducts收藏
  • $lookupcolors收藏
  • $addFields,$arrayElemAt从查找结果中获取第一个元素
  • $group通过_id并重建items数组并传递其他字段
  • 聚合函数中没有外部方法,您必须使用阶段进行排序、跳过和限制,如下所示
  • $sortaddedDate降序排列
  • $skip$limit结果
const moves = await ProductMoves.aggregate([
  { $match: query }, // this is my query
  { $unwind: "$items" },
  {
    $lookup: {
      from: "products",
      localField: "items.itemId",
      foreignField: "_id",
      as: "itemId"
    }
  },
  {
    $lookup: {
      from: "colors",
      localField: "items.itemColor",
      foreignField: "_id",
      as: "itemColor"
    }
  },
  {
    $addFields: {
      "items.itemId": { $arrayElemAt: ["$itemId.productName", 0] },
      "items.itemColor": { $arrayElemAt: ["$itemColor.name", 0] }
    }
  },
  {
    $group: {
      _id: "$_id",
      items: { $push: "$items" },
      addedDate: { $first: "$addedDate" }
      // add other fields that you want in result like "addedDate"
    }
  },
  { $sort: { addedDate: -1 } },
  { $skip: +req.query.offset },
  { $limit: +req.query.limit }
])

操场


推荐阅读