1

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

我尝试带上所有的饭菜,并使用 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”字段在“产品”系列中查找其产品。然后我将总结所有产品的营养成分以获得膳食营养成分。

示例产品文档

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

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

4

1 回答 1

0

对于每顿饭,我需要使用“sku”字段在“产品”系列中查找其产品。然后我将总结所有产品的营养成分以获得膳食营养成分。

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)不是正确的语法。更新操作使用更新运算符。更正后的代码:db.Meals.updateOne( { _id: meal._id }, { $set: { nutri_facts: nutri_facts_v } } ). 请注意,我们仅更新 nutifacts,而不是所有详细信息。
  4. 由于单独的营养成分被存储为字符串(例如,“100kcal”),因此在算术过程中字符串部分被剥离。因此,我们为每个营养成分捕获字符串单位(例如,“kcal”),然后在算术之后附加它。以下代码剥离并存储单位部分:let units = (product.nutri_facts[nutriFact].split(/\d+/)).pop().
  5. 使用mongo shell方法printprintjson分别打印变量或对象的内容 - 用于调试目的。

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

于 2020-01-02T07:01:08.993 回答