You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 16:33:28