根据另一个集合数据更新 mongo 字段

Update a mongo field based on another collections data

我正在寻找一种基于另一个集合的数据总和来更新字段的方法。

我试着带上所有的饭菜,并使用 forEach 为每顿饭调用 Products 集合,测试它是否有效,但我超时了。

meals.find().forEach(meal => {
    var products = db.Products.find(
        { sku: { $in: meal.products } },
        { _id: 1, name: 1, sku: 1, nutritional_facts: 1 }
    )
    printjson(products)
})

我的目标是执行下面这样的操作以获得所需的结果,但我得到了 "SyntaxError: invalid for/in left-hand side"。无法在 mongo 查询中使用 for in 吗?

db.Meals.find({}).forEach(meal => {

    const nutri_facts = {};

    db.Products.find({ sku: { $in: meal.products } }, 
    { _id: 1, name: 1, sku: 1, nutri_facts: 1 }).forEach(product => {
        for (let nutriFact in product.nutri_facts) {
            nutri_facts[nutriFact] =
                    parseFloat(nutri_facts[nutriFact]) +
                    parseFloat(product.nutri_facts[nutriFact]);
            }
        }
    });

    for (let nutriFact in nutri_facts) {
            meal.nutri_facts[nutriFact] = 
            nutri_facts[nutriFact];
        }
    }

    db.Meals.updateOne({ _id: meal._id }, meal)
});

在这种情况下,我也很难弄清楚如何使用聚合和查找,但没有成功。

可以吗?

示例 - 膳食文档

{
  _id: ObjectId("..."),
   products : ["P068","L021","L026"], //these SKUs are part of this meal
   nutri_facts: {
    total_fat: 5g,
    calories: 100kcal
    (...other properties)
   }
}

对于每顿饭,我都需要使用 'sku' 字段在 'Products' 集合中查找它的产品。 然后我会总结所有产品的营养成分,得到这顿饭的营养成分。

示例产品文档

{
  _id: ObjectId("..."),
   sku: 'A010'
   nutri_facts: {
    total_fat: 2g,
    calories: 40kcal
    (...other properties)
   }
}

我知道 mongo 在这种情况下可能不是最佳选择,但整个应用程序已经使用它构建。

For each meal I need to look for its products on 'Products' collections using 'sku' field. Then I will sum the nutritional facts of all products to get the meal nutritional facts.

db.Meals.find( { } ).forEach( meal => {

    // print(meal._id);
    const nutri_facts_var = { };

    db.Products.find( { sku: { $in: meal.products } }, { nutri_facts: 1 }.forEach( product => {

         // printjson(product.nutri_facts);

        for ( let nutriFact in product.nutri_facts ) {

            let units = (product.nutri_facts[nutriFact].split(/\d+/)).pop();
            // print(units)

            // Checks for the existence of the field and then adds or assigns
            if ( nutri_facts_var[nutriFact] ) {
                nutri_facts_var[nutriFact] = parseFloat( nutri_facts_var[nutriFact] ) + parseFloat( product.nutri_facts[nutriFact] );
            }
            else {
                nutri_facts_var[nutriFact] = parseFloat( product.nutri_facts[nutriFact] );
            }

            nutri_facts_var[nutriFact] = nutri_facts_var[nutriFact] + units;
        }

    } );

   // printjson(nutri_facts_var);

   db.Meals.updateOne( { _id: meal._id }, { $set: { nutri_facts: nutri_facts_var } } );
} );


备注:

  1. 我使用变量nutri_facts_var名称(var后缀)所以 我们可以轻松区分用户定义的变量名称 文档字段名称。
  2. { _id: 1, name: 1, sku: 1, nutri_facts: 1 } 改为 { nutri_facts: 1}。默认情况下,_id 包含 投影。不需要字段 namesku
  3. db.Meals.updateOne({ _id: meal._id }, meal) 不正确 句法。更新操作使用 Update 运算符。 更正后的代码:db.Meals.updateOne( { _id: meal._id }, { $set: { nutri_facts: nutri_facts_v } } )。请注意,我们正在更新 只有细节,不是所有细节。
  4. 由于单个营养素以字符串形式存储(例如, “100kcal”),在算术过程中字符串部分被剥离。所以,我们 为每个营养素捕获字符串 units(例如,"kcal")和 稍后将其附加在算术之后。下面的代码条和 存储 units 部分:let units = (product.nutri_facts[nutriFact].split(/\d+/)).pop().
  5. 使用mongoshell方法printprintjson打印 变量或对象的内容分别用于调试 目的。

请注意,即使未在其中定义 nutri_facts 字段,查询也会更新 Meal 集合; $set 更新运算符创建新字段并设置值以防字段不存在。