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

Sequelize新手求助:如何根据country_iso2关联插入数据到contact表

问题描述

我是Sequelize新手,已创建两张表:

  • contact表:字段为id、name、nationalNumber、countryId
  • countries表:字段为id、iso2

API接收的数组数据格式如下:

[
    {
        "name": "Aftab",
        "mobile_number": "3408906107",
        "name_check": 0,
        "country_iso2": "PK"
    },
    {
        "name": "Numan Jhanger",
        "mobile_number": "3179608039",
        "name_check": "0",
        "country_iso2": "PK"
    },
    {
        "name": "Muhammad Zaki",
        "mobile_number": "3175623123",
        "name_check": 0,
        "country_iso2": "PK"
    },
    {
        "name": "Irshad Khan",
        "mobile_number": "3428890654",
        "name_check": 0,
        "country_iso2": "PK"
    }
]

需求是根据每条数据的country_iso2从countries表获取对应的id,再将数据插入contact表。现有代码中country_id写死为167,需要替换为动态获取的ID:

async function create(data) {
  return new Promise(async (resolve, reject) => {
    data.contacts.map(async (item, index) => {
      let ios2 = item.country_iso2;
      delete item.country_iso2;
      await db.filtered_contacts
        .findOrCreate({
          where: { mobile_number: item.mobile_number },
          defaults: { ...item, country_id: 167 },
        })
        .then(([item, created]) => {
          console.log(item); // John
          console.log(created); // true
        });
    });

    resolve("dsds");
  });
}

已正确定义表关联关系:

// countries and filter contact relations
db.countries.hasMany(db.filtered_contacts, {
  foreignKey: "country_id",
});
db.filtered_contacts.belongsTo(db.countries, {
  foreignKey: "country_id",
});

需要指导如何实现根据country_iso2获取countryId并完成插入。

解决方案

1. 核心修改思路

  • 先通过country_iso2查询对应国家的ID
  • 修正原代码中异步逻辑的缺陷(map+async无法正确等待、外层Promise冗余)
  • 处理数据类型统一、异常情况(如未找到对应国家)

2. 基础版本代码

async function create(data) {
  try {
    // 用Promise.all等待所有异步操作完成,避免提前resolve
    await Promise.all(data.contacts.map(async (item) => {
      // 解构拆分字段,分离出需要处理的国家编码
      const { country_iso2, mobile_number, ...rest } = item;
      
      // 根据iso2查询对应国家的ID,只获取需要的字段提升性能
      const country = await db.countries.findOne({
        where: { iso2: country_iso2 },
        attributes: ['id']
      });

      // 处理未找到国家的情况,避免无效插入
      if (!country) {
        console.warn(`未找到iso2为${country_iso2}的国家记录,跳过该联系人`);
        return;
      }

      // 统一name_check的类型(原数据存在数字/字符串混合的情况)
      const normalizedData = {
        ...rest,
        mobile_number,
        name_check: Number(rest.name_check),
        country_id: country.id
      };

      // 执行findOrCreate操作
      const [contact, created] = await db.filtered_contacts.findOrCreate({
        where: { mobile_number },
        defaults: normalizedData
      });

      console.log(`联系人${contact.name} ${created ? '已创建' : '已存在'}`);
    }));

    return '所有联系人处理完成';
  } catch (error) {
    console.error('处理联系人时出错:', error);
    throw error; // 抛出错误让调用方处理
  }
}

3. 大数据量优化版本

如果需要处理的联系人数据较多,每条单独查询国家会产生大量数据库请求,建议先批量查询所有涉及的国家,再通过映射表匹配ID:

async function create(data) {
  try {
    // 收集所有唯一的国家编码,避免重复查询
    const uniqueIso2s = [...new Set(data.contacts.map(item => item.country_iso2))];
    
    // 批量查询所有涉及的国家
    const countries = await db.countries.findAll({
      where: { iso2: uniqueIso2s },
      attributes: ['id', 'iso2']
    });

    // 构建iso2到id的映射表
    const iso2ToIdMap = {};
    countries.forEach(country => {
      iso2ToIdMap[country.iso2] = country.id;
    });

    // 批量处理联系人数据
    await Promise.all(data.contacts.map(async (item) => {
      const { country_iso2, mobile_number, ...rest } = item;
      const countryId = iso2ToIdMap[country_iso2];

      if (!countryId) {
        console.warn(`未找到iso2为${country_iso2}的国家记录,跳过该联系人`);
        return;
      }

      const normalizedData = {
        ...rest,
        mobile_number,
        name_check: Number(rest.name_check),
        country_id: countryId
      };

      const [contact, created] = await db.filtered_contacts.findOrCreate({
        where: { mobile_number },
        defaults: normalizedData
      });

      console.log(`联系人${contact.name} ${created ? '已创建' : '已存在'}`);
    }));

    return '所有联系人处理完成';
  } catch (error) {
    console.error('处理联系人时出错:', error);
    throw error;
  }
}

内容的提问来源于stack exchange,提问作者Engr.Aftab Ufaq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:46:34