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

使用Mongoose和Express导入国家JSON到MongoDB集合创建失败如何解决

问题排查与修复方案

核心问题汇总

  • 异步操作未等待:Country.insertMany() 是异步方法,原代码未加await关键字,导致请求在数据库写入操作完成前就返回,写入逻辑未执行完成就提前结束。
  • Schema类型不匹配:
    1. latitude 字段被错误定义为Date类型,实际传入的是纬度字符串,类型校验失败导致数据无法写入。
    2. timezones子文档中的gmtOffset字段被定义为String类型,但数据源中该字段是数字类型,类型校验失败。

修正后的Mongoose Schema定义

const mongoose = require('mongoose');
const { toJSON, paginate } = require('./plugins');

const countriesSchema = new mongoose.Schema(
    {
        uniqueId: { type: String, default: null },
        // 如果你需要保留原数据的数字类型,可以改为 type: Number
        countryId: { type: String, default: null },
        name: { type: String, default: null },
        iso3: { type: String, default: null },
        iso2: { type: String, default: null },
        numeric_code: { type: String, default: null },
        phone_code: { type: String, default: null },
        capital: { type: String, default: null },
        currency: { type: String, default: null },
        currency_symbol: { type: String, default: null },
        tld: { type: String, default: null },
        native: { type: String, default: null },
        region: { type: String, default: null },
        subregion: { type: String, default: null },
        timezones: [{
            zoneName: {
                type: String,
                trim: true,
                default: null
            },
            // 修正为Number类型匹配数据源
            gmtOffset: {
                type: Number,
                trim: true,
                default: null
            },
            gmtOffsetName: {
                type: String,
                trim: true,
                default: null
            },
            abbreviation: {
                type: String,
                trim: true,
                default: null
            },
            tzName: {
                type: String,
                trim: true,
                default: null
            },
        }],
        // 修正为String类型匹配传入的纬度值
        latitude: { type: String, default: null },
        longitude: { type: String, default: null },
        emoji: { type: String, default: null },
        settings: {
            preferred_intl_destinations: [{
                destinationName: { type:String, default: null },
                destinationId: { type:String, default: null },
                destinationImg: {
                      imageId: { type:String, default: null },
                      imageUrl: { type:String, default: null }
                 },
            }],
            preferred_domestic_destinations: [{
                destinationName: { type: String, default: null },
                destinationId: { type: String, default: null },
                destinationImg: {
                    imageId: { type: String, default: null },
                    imageUrl: { type: String, default: null }
                },
            }],
        }
    },
    {
        timestamps: true,
    }
);

countriesSchema.plugin(toJSON);
countriesSchema.plugin(paginate);

const Country = mongoose.model('ttc_Countries', countriesSchema);

module.exports = Country;

修正后的控制器代码

const { Country } = require('../models');
// 确保已经引入axios和uuidv4
const axios = require('axios');
const { v4: uuidv4 } = require('uuid');

const addCountrytoDatabase = catchAsync(async (req, res) => {
    const { data: countries } = await axios.get(`https://raw.githubusercontent.com/dr5hn/countries-states-cities-database/master/countries.json`);
    const countrieslist = countries.map(item => ({
        uniqueId: uuidv4(),
        // 如果Schema中countryId改为Number类型,这里不需要转字符串
        countryId: String(item.id),
        name: item.name,
        iso3: item.iso3,
        iso2: item.iso2,
        numeric_code: item.numeric_code,
        phone_code: item.phone_code,
        capital: item.capital,
        currency: item.currency,
        currency_symbol: item.currency_symbol,
        tld: item.tld,
        native: item.native,
        region: item.region,
        subregion: item.subregion,
        timezones: item.timezones,
        latitude: item.latitude,
        longitude: item.longitude,
    }));
    // 加await等待写入完成
    const createdCountries = await Country.insertMany(countrieslist);
    res.status(201).send(createdCountries);
});

补充说明

如果不需要保留emoji和settings相关字段,可以直接从Schema中删除对应定义,减少冗余存储。如果需要避免重复插入国家数据,可以给countryId或者iso2字段添加唯一索引。

内容的提问来源于stack exchange,提问作者Vinay Thakur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:06:02