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

Adonis JS中如何高效插入多层关联数据?无需循环操作

在AdonisJS中批量插入多层关联数据的优化方案

我是Adonis JS新手,在插入多层关联数据时遇到困难。现有countries、cities、shops三张表,关系为Countries拥有多个Cities,Cities拥有多个Shops。当需要批量插入数据(如1个国家、5个城市、20个店铺)时,是否有无需循环的简便方法?

当前我的实现思路用了while循环处理店铺关联,希望找到更简便的替代方案。


优化后的实现代码

const countryName = request.input('country')
const citiesData = request.input('data') // 结构示例: [{ name: '北京', shops: [{ name: 'XX超市' }, ...] }, ...]

const trx = await Database.transaction()

try {
  // 1. 创建国家
  const country = await Country.create({ name: countryName }, { client: trx })

  // 2. 并行处理所有城市及对应的店铺,替代while循环
  await Promise.all(citiesData.map(async (cityItem) => {
    // 创建或更新当前城市
    const city = await country.related('cities').updateOrCreate(
      { name: cityItem.name },
      { name: cityItem.name },
      { client: trx }
    )
    // 批量创建或更新该城市下的店铺
    await city.related('shops').updateOrCreateMany(cityItem.shops, 'name')
  }))

  // 3. 预加载完整的关联数据返回
  const savedCountry = await Country.query({ client: trx })
    .where('id', country.id)
    .preload('cities', (query) => query.preload('shops'))
    .first()

  await trx.commit()
  return response.status(200).json({ message: 'saved', data: savedCountry })
} catch (error) {
  await trx.rollback()
  return response.status(500).json({ message: '保存失败', error: error.message })
}

核心优化点

  • 用Promise.all替代while循环:代码更简洁,同时实现并行处理(若需顺序执行可改用for...of循环),避免冗余的索引管理和重复查询
  • 减少数据库查询次数:直接使用创建/更新后的城市实例操作店铺关联,无需重新查询城市数据
  • 规范事务处理:所有操作都在同一个事务中,修复了原代码循环内提交事务的错误,确保出错时能完整回滚
  • 简化数据加载流程:创建完成后直接通过事务查询预加载所有关联数据,确保获取到最新的完整数据

原代码的主要问题

  1. 事务提交位置错误:原代码在while循环内提交事务,导致第一次循环后事务就已完成,后续的店铺操作不在事务保护范围内,出错无法回滚
  2. 冗余查询:序列化国家后重新查询城市,完全可以直接使用创建城市时得到的实例
  3. 数据一致性问题:最后查询结果时未传入事务对象,可能无法获取到事务中未提交的最新数据

内容的提问来源于stack exchange,提问作者Humphrey Singculan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 16:15:38