首页 > 解决方案 > 如何对一个集合中多个文档的值求和并将总和推送到另一个集合中的文档

问题描述

我有食谱和配料。每个都有自己的模型,每个都有自己的控制器。每个食谱都有多种成分。在配方模型中,成分被列为成分 ID 数组(在下面的代码中,我在配方模型中将它们称为 ingIds)。每种成分可以属于多个配方。每种成分都有卡路里量。在成分模型中,我将字段命名为卡路里。我正在尝试根据配方中所有成分的总卡路里量以编程方式总计每个配方的卡路里量。我有下面的代码似乎可以工作,有点。当我得到所有食谱时,我在 Postman 中得到了正确的结果。但是,我无法获取 mongodb 中的数据来更新食谱文档中的总卡路里计数(我命名为“分数”的卡路里计数字段)。知道我做错了什么吗?

我尝试使用成分文档填充配方模型,然后对嵌套的卡路里字段求和,但我不知道如何对嵌套的卡路里字段的总数求和。在发布期间使用嵌入式 url 创建新成分时,我还成功地计算了总数并将其发布到数据库中,但这不起作用,因为只有当成分仅属于一个食谱时,这才是好的。在这里,我有属于多个食谱的成分。

以下是我目前处理此问题的代码片段。配方模型具有一系列成分 ID。配方控制器查看具有匹配 ID 的成分文档。然后,从匹配的成分文档中,配方控制器对卡路里字段求和并将其保存到“分数”。当我在邮递员中获得所有食谱时,邮递员中的输出是正确的。它显示具有正确值的分数字段。但是,mongodb 数据库不会更新配方文档中的 score 字段。

// 配方控制器

...

exports.getPostTotals = catchAsync(async (req, res, next) => {
const stats = await Post.aggregate([
    {
      $lookup: {
        from: "ingredients", // name of the foreign collection
        localField: "ingIds",
        foreignField: "_id",
        as: "lookup-data"
      }
    },
    {
      $addFields: {
        score: {
          $sum: "$lookup-data.calories"
        }
      }
    },
    { $project: { "lookup-data": 0 } }
  ]);
  res.status(200).json({
    status: "success",
    data: {
      stats
    }
  });
});

...

// 配方模型 //

const mongoose = require("mongoose");
const slugify = require("slugify");

const postSchema = new mongoose.Schema(
  {
    ...

    ingIds: [{ type: mongoose.Schema.ObjectId, ref: "Ingredient" }],
    score: Number,
    ...

  },
  {
    toJSON: { virtuals: true },
    toObject: { virtuals: true }
  }
);

...

const Post = mongoose.model("Post", postSchema);

module.exports = Post;

// 成分模型 //

const mongoose = require("mongoose");
const Post = require("./postModel");

const ingredientSchema = new mongoose.Schema(
  {
    ...

    calories: {
      type: Number,
      required: [true, "An ingredient must have a calorie count."]
    ...

  },
  {
    toJSON: { virtuals: true },
    toObject: { virtuals: true }
  }
);

const Ingredient = mongoose.model("Ingredient", ingredientSchema);

module.exports = Ingredient;

标签: javascriptnode.jsmongodbmongoosesum

解决方案


顺便说一句,你在哪里将分数值写回 MongoDB?在这里您使用聚合 - 这意味着 $addFields - 只是将新字段添加到聚合的前一阶段的文档中,以便聚合的下一阶段找到这些字段,这意味着聚合的输出包含这些字段。但它不会将其存储在数据库中。

如果要将聚合结果写回数据库,请使用 $out 或 $merge

请参阅https://docs.mongodb.com/manual/reference/operator/aggregation/out/

https://docs.mongodb.com/manual/reference/operator/aggregation/merge/


推荐阅读