JS遍历对象生成关联数据插入数据库时字段取值匹配问题
问题背景
我正在尝试通过现有对象的取值创建一系列新对象,将数据写入数据库。
现有待处理对象结构如下:
{ name: 'Pasta', method: 'Cook pasta', ingredients: [ { measure: 'tbsp', quantity: '1', ingredient_name: 'lemon' }, { measure: 'g', quantity: '1', ingredient_name: 'salt' }, { measure: 'packet', quantity: '1', ingredient_name: 'spaghetti' }, { measure: 'litre', quantity: '1', ingredient_name: 'water' } ] }
业务逻辑流程:
- 先向
recipes表插入食谱基础数据,返回生成的食谱自增id - 插入或查询匹配到对应配料的id
- 将返回的
recipe_id、ingredient_id与原对象中对应正确的measure、quantity字段值组合为关联表数据,写入食谱-配料关联表
当前编写的存在问题的代码如下:
//starting point is here async function addNewRecipe(newRecipe, db = connection) { console.log(newRecipe) const recipeDetails = { recipe_name: newRecipe.name, recipe_method: newRecipe.method, } const ingredientsArray = newRecipe.ingredients const [{ id: recipeId }] = await db('recipes') .insert(recipeDetails) .returning('id') const ingredientsWithIds = await getIngredients(ingredientsArray) //returns an array of ids ingredientsWithIds.forEach((ingredientId) => { let ingredientRecipeObj = { recipe_id: recipeId, //works ingredient_id: ingredientId, //works measure: newRecipe.ingredients.measure, //not working - not sure how to match it with the relevant property in the newRecipe object above. quantity: newRecipe.ingredients.quantity,//not working - not sure how to match it with the relevant property in the newRecipe object above. } //this is where the db insertion will occur }) }
期望生成的关联表数据结构如下,依次插入数据库:
ingredientRecipeObj = { recipe_id: 1, ingredient_id: 1, measure: 'tbsp', quantity: '1' } // 插入第一条后再生成第二条 ingredientRecipeObj = { recipe_id: 1, ingredient_id: 2, measure: 'g', quantity: '1' } // 后续配料按相同逻辑生成插入
当前代码问题:遍历配料id数组时,无法正确匹配到对应配料项的measure和quantity取值,生成的关联表数据字段错误,不满足入库要求。
问题原因
代码中newRecipe.ingredients是数组类型,直接访问newRecipe.ingredients.measure本质是访问数组对象的measure属性,拿到的永远是undefined,自然无法取到对应配料的字段值。
只要getIngredients返回的id数组顺序和传入的ingredientsArray顺序严格一一对应,就可以通过遍历索引匹配到原数组对应项的字段。
修正代码
推荐直接批量生成所有关联记录后一次性插入,比循环单条插入性能更好:
async function addNewRecipe(newRecipe, db = connection) { const recipeDetails = { recipe_name: newRecipe.name, recipe_method: newRecipe.method, } const ingredientsArray = newRecipe.ingredients // 插入食谱拿到id const [{ id: recipeId }] = await db('recipes') .insert(recipeDetails) .returning('id') // 拿到按传入顺序返回的配料id数组 const ingredientsWithIds = await getIngredients(ingredientsArray) // 按索引匹配原配料项的字段,生成所有关联表记录 const recipeIngredientList = ingredientsWithIds.map((ingredientId, index) => { const matchedIngredient = ingredientsArray[index] return { recipe_id: recipeId, ingredient_id: ingredientId, measure: matchedIngredient.measure, quantity: matchedIngredient.quantity } }) // 批量插入关联表,替换成你实际的关联表名即可 await db('recipe_ingredients').insert(recipeIngredientList) return recipeId }
稳妥性优化
如果无法保证getIngredients返回的id顺序和传入顺序一致,可以修改getIngredients函数,让它返回带ingredient_name的完整对象数组而非纯id数组,通过配料名做精确匹配,完全避免顺序错乱导致的数据匹配错误。
内容的提问来源于stack exchange,提问作者deadant88
相关产品推荐
相关产品推荐

