首页 > 解决方案 > 猫鼬骨料

问题描述

我需要一些有关 Mongo、Mongoose 和 Node.js 的帮助。

在下面的代码中,我想加入carrinhoprodutos收集来检索produtos _idprice并且description在同一个数组/对象中。

我的Carrinho架构

 const Carrinho = new mongoose.Schema(
   {
     title: {
       type: String,
     },
     produtos: [{
       price: Number,
       produto: { type: mongoose.Schema.Types.ObjectId, ref: 
 "Produtos" }
     }
     ],
     total: {
       type: Number,
     },
   },
     {
       timestamps: true


     })

我的Produtos架构

   const Produtos = new mongoose.Schema(
     {
description: {
  type: String,
  required: true,
},
gtin: {
  type: String,
  required: true,
  unique: true,
},
thumbnail: {
  type: String,

},
price: {
  type: Number,
}
     },
     {
       timestamps: true
     }
   )

阅读aggregate文档后,这是我得到的最好的:

    Carrinho.aggregate([
  { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
  {
    "$lookup": {
      "from": "produtos",
      "localField": "produtos._id",
      "foreignField": "_id",
      "as": "produtosnocarrinho"
    }
  },
  {
    "$addFields": {
      "total": {
        "$reduce": {
          "input": "$produtos",
          "initialValue": 0,
          "in": { "$add": ["$$value", "$$this.price"] }
        }
      }
    }
  }
]).exec((err, data) => {
  if (err) res.json(err)

  res.json(data)
});

这是结果:

   [
     {
"_id": "5cb76d7d99c3f4062f512537",
"title": "Carrinho do Lucas",
"produtos": [
  {
    "_id": "5cafead2bc648978100d7698",
    "price": 20.1
  },
  {
    "_id": "5cae911adf75ac4d3ca4bcb6",
    "price": 20.1
  },
  {
    "_id": "5cb0f0adc5fb29105d271499",
    "price": 20.1
  }
],
"createdAt": "2019-04-17T18:16:29.833Z",
"updatedAt": "2019-04-19T00:50:43.316Z",
"__v": 3,
"produtosnocarrinho": [
  {
    "_id": "5cae911adf75ac4d3ca4bcb6",
    "description": "AÇÚCAR REFINADO UNIÃO 1KGS",
    "gtin": "7891910000197",
    "thumbnail": "7891910000197",
    "createdAt": "2019-04-11T00:58:02.296Z",
    "updatedAt": "2019-04-11T00:58:02.296Z",
    "__v": 0
  },
  {
    "_id": "5cafead2bc648978100d7698",
    "description": "HASBRO MR. POTATO HEAD MALETA DE PEÇAS",
    "gtin": "5010994598815",
    "thumbnail": "pecas_300x300-PU3435f_1.jpg",
    "createdAt": "2019-04-12T01:33:06.628Z",
    "updatedAt": "2019-04-12T01:33:06.628Z",
    "__v": 0
  },
  {
    "_id": "5cb0f0adc5fb29105d271499",
    "description": "REPELENTE EXPOSIS INFANTIL SPRAY",
    "gtin": "7898392800055",
    "thumbnail": "PU28bb9_1.jpg",
    "createdAt": "2019-04-12T20:10:21.363Z",
    "updatedAt": "2019-04-12T20:10:21.363Z",
    "__v": 0
  }
],
"total": 60.300000000000004
     }
   ]

标签: node.jsmongooseaggregatemongoose-schema

解决方案


以下查询将有所帮助:

 models.Carrinho.aggregate(
    [     
        { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
        {
            "$lookup": {
              "from": "produtos",
              "localField": "produtos._id",
              "foreignField": "_id",
              "as": "produtosnocarrinho"
            }
          },
          {
            "$addFields": {
              "total": {
                "$reduce": {
                  "input": "$produtos",
                  "initialValue": 0,
                  "in": { "$add": ["$$value", "$$this.price"] }
                }
              }
            }
          },
          {$unwind : '$produtos'},
          {$unwind : '$produtosnocarrinho'},
          {$redact: { $cond: [{
                                  $eq: [
                                         "$produtos._id",
                                         "$produtosnocarrinho._id"
                                       ]
                                },
                                "$$KEEP",
                                "$$PRUNE"
                              ]
                      }
            },
            { $project: {
                     _id : 1,
                     title : 1,
                     produtosData : {
                        _id : "$produtos._id",
                        price : "$produtos.price",
                        description : "$produtosnocarrinho.description"
                     },
                     total : 1,
                     createdAt:  1,
                     updatedAt : 1
                }
           },
           {
              $group : {
                    _id : {
                        _id : '$_id',
                        title : '$title',
                        total : '$total',
                        createdAt  : '$createdAt',
                        updatedAt : '$updatedAt'
                    },
                    produtosData: {$push: "$produtosData" }
              }
           },
           { $project: {
                    _id  : '$_id._id',
                    title : '$_id.title',
                    total : '$_id.total',
                    createdAt  : '$_id.createdAt',
                    updatedAt : '$_id.updatedAt',
                    produtosData:  '$produtosData'
                }
           }
    ]).exec((err, data) => {
        if (err) res.json(err)

        res.json(data)
      });


Output : 
[{
    "_id": "5cbc42c24502a7318952d7b2",
    "title": "Carrinho do Lucas",
    "total": 60.300000000000004,
    "createdAt": "2019-04-21T10:15:30.629Z",
    "updatedAt": "2019-04-21T10:15:30.629Z",
    "produtosData": [{
        "_id": "5cafead2bc648978100d7698",
        "price": 20.1,
        "description": "HASBRO MR. POTATO HEAD MALETA DE PEÇAS"
    }, {
        "_id": "5cae911adf75ac4d3ca4bcb6",
        "price": 20.1,
        "description": "AÇÚCAR REFINADO UNIÃO 1KGS"
    }, {
        "_id": "5cb0f0adc5fb29105d271499",
        "price": 20.1,
        "description": "REPELENTE EXPOSIS INFANTIL SPRAY"
    }]
}]

性能取决于来自 Lookup Query 的产品匹配数据,因为我们正在做双重展开。


推荐阅读