1. 本地 JSON 灌库这件事,为什么总在最后一步卡住
如果你正在写 Node 项目,手里有一份几百上千条的本地 JSON,想批量塞进 MongoDB,大概率会经历这么几个阶段:先用 MongoDB Compass 点几下导入,数据量小还行,字段一多就发现类型全乱了;然后换成写个 seeder.js,用 mongoose 的create()一条条插,跑是能跑,但几千条下去速度肉眼可见地慢;最后才想起命令行里那个mongoimport,结果又卡在路径、JSON 格式、认证参数上。
这篇就聚焦一件事:在 Node 项目里,用mongoimport把本地 JSON 批量导入 MongoDB,一次跑通,并且导入完能立刻用查询验证条数和字段映射对不对。同时我会补上 TaoToken 统一 Key 的配置片段,因为现在很多项目里模型调用和数据库操作是同一个后端服务在跑,Key 管理散落在各处很容易出问题,统一到一个 settings.json 里会省心很多。
适合谁看:已经会写基本 mongoose 连接、但导入环节还在手动复制粘贴或者用 Compass 点来点去的同学;以及项目里同时有 AI 接口调用和数据库 seed 需求、想把配置收拢的人。下面所有命令和配置都可以直接复制改路径就用。
2. 前置准备:mongoimport 从哪来,TaoToken Key 怎么统一管
2.1 mongoimport 不是 npm 包,别去 npm install
这是第一个容易踩的坑。mongoimport是 MongoDB Database Tools 的一部分,不在 npm 生态里。你npm i mongoimport是装不到的。正确做法是装 MongoDB 命令行工具:
macOS 用 Homebrew:
brew tap mongodb/brew brew install mongodb-database-toolsWindows 去 MongoDB 官网下载 Database Tools 的 zip,解压后把bin目录加到系统 PATH。Linux 用对应的包管理器装mongodb-database-tools。
装完验证:
mongoimport --version能打印版本号就说明工具链通了。这一步不通,后面所有命令都会报command not found。
2.2 为什么要在 Node 项目里引入 TaoToken 统一 Key
很多 Node 项目的目录结构是这样的:数据库连接写在config/db.js,模型调用写在services/ai.js,然后 API Key 一半在.env,一半硬编码在某个文件里。项目一多人协作,Key 就到处飞。
TaoToken 的做法是提供一个统一的 API 通道,把模型调用相关的 Key 和地址收拢到一份配置里。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。你可以在控制台里生成 Key,然后项目里只认这一份 settings.json,数据库 seed 脚本和 AI 调用脚本共用同一套读取逻辑。
具体来说,你需要在项目根目录建一个config/settings.json,把 TaoToken 的 Key 和 base URL 放进去,Node 侧用fs.readFileSync读,避免每个文件都process.env.XXX散落。下面第三节会给完整片段。
3. 可复制配置:mongoimport 命令骨架 + mongoose 连接 + settings.json
3.1 mongoimport 命令行骨架
假设你的本地 JSON 放在项目_data/courses.json,数据库叫api,集合叫courses,本地 MongoDB 没开认证:
mongoimport \ --db api \ --collection courses \ --file ./_data/courses.json \ --jsonArray \ --drop几个参数逐个说清楚:
| 参数 | 作用 | 注意点 |
|---|---|---|
--db | 目标数据库名 | 不存在会自动创建 |
--collection | 目标集合名 | 同上 |
--file | JSON 文件路径 | 相对路径以执行命令的目录为准 |
--jsonArray | 文件是数组格式 | 不加这个会按每行一个对象解析,数组文件直接报错 |
--drop | 导入前清空集合 | 重复跑不会叠加数据,调试期很有用 |
如果你的 JSON 是每行一个对象的 NDJSON 格式,就去掉--jsonArray。判断方法很简单:文件开头是[就是数组,是{且每行独立就是 NDJSON。
开了认证的 MongoDB 要加:
mongoimport \ --uri "mongodb://用户名:密码@localhost:27017/api?authSource=admin" \ --collection courses \ --file ./_data/courses.json \ --jsonArray \ --drop用--uri比拆成--host --username --password更省事,认证库用authSource指定。
3.2 mongoose 连接配置
导入完成后,Node 侧要能连上同一个库做查询验证。config/db.js:
const mongoose = require('mongoose') const connectDB = async () => { try { const conn = await mongoose.connect('mongodb://localhost:27017/api', { useNewUrlParser: true, useUnifiedTopology: true, }) console.log(`MongoDB connected: ${conn.connection.host}`) } catch (err) { console.error(`连接失败: ${err.message}`) process.exit(1) } } module.exports = connectDB注意useNewUrlParser和useUnifiedTopology在新版 mongoose 里已经默认开启,写不写都行,但老项目里保留着不会报错。连接串里的库名api必须和mongoimport --db一致,否则你导入到 A 库、查询查 B 库,会得到「数据明明导了却查不到」的经典问题。
3.3 TaoToken 统一 Key 的 settings.json 片段
在项目根目录建config/settings.json:
{ "taotoken": { "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的Key", "defaultModel": "claude-sonnet-4-20250514" }, "mongo": { "uri": "mongodb://localhost:27017/api" } }Node 侧统一读取:
const fs = require('fs') const path = require('path') const settings = JSON.parse( fs.readFileSync(path.join(__dirname, '../config/settings.json'), 'utf-8') ) const { baseUrl, apiKey } = settings.taotoken const mongoUri = settings.mongo.uri这样 seed 脚本、AI 调用脚本、数据库连接都从同一份配置取,改 Key 只改一个地方。Key 的生成入口在控制台,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,生成后直接填进apiKey字段。如果你后面要接 Claude Code 这类编码工具,配置文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有针对不同客户端的 settings 写法。
注意:settings.json 里含 Key,务必加进
.gitignore,别提交到仓库。团队协作时用 settings.example.json 占位。
4. 验证请求:导入条数与字段映射怎么查
4.1 先看 mongoimport 的输出
导入命令跑完,终端会打印类似:
2025-01-15T10:23:45.123+0800 connected to: mongodb://localhost:27017 2025-01-15T10:23:45.456+0800 dropping: api.courses 2025-01-15T10:23:46.789+0800 1200 document(s) imported successfully. 0 document(s) failed to import.重点看两个数字:imported successfully和failed to import。如果 failed 不为 0,说明有文档字段类型和集合已有 schema 冲突,或者 JSON 里有非法字符。这时候别急着往下走,先把失败原因解决掉。
4.2 用 mongosh 查条数
mongosh use api db.courses.countDocuments()返回的数字应该和 mongoimport 输出的 imported 数量一致。如果不一致,检查是不是没加--drop导致重复导入叠加了。
4.3 用 mongoose 查字段映射
光看条数不够,字段映射错了照样是废数据。写个验证脚本verify.js:
const mongoose = require('mongoose') const connectDB = require('./config/db') const courseSchema = new mongoose.Schema({}, { strict: false }) const Course = mongoose.model('Course', courseSchema, 'courses') const verify = async () => { await connectDB() const total = await Course.countDocuments() console.log(`总条数: ${total}`) const sample = await Course.findOne().lean() console.log('首条文档字段:', Object.keys(sample)) const missingTitle = await Course.countDocuments({ title: { $exists: false } }) console.log(`缺少 title 字段的文档数: ${missingTitle}`) await mongoose.connection.close() } verify()这里用strict: false是为了不预先定义 schema 也能查,适合导入后快速验证。跑node verify.js,输出会告诉你总条数、首条文档有哪些字段、以及关键字段缺失的数量。如果missingTitle很大,说明你的 JSON 里字段名和预期不一致,比如写成了courseName而不是title,这时候要么改 JSON,要么在导入前用脚本做字段重映射。
4.4 用 TaoToken 模型对话做字段语义核对
有时候字段名对得上,但值的语义不对,比如price字段里混进了字符串"免费"。这种可以调模型帮你扫一遍样本。用模型对话入口 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite ,把几条样本贴进去,让它判断字段类型是否一致。这一步不是必须的,但在数据源不规范时能省不少人工核对时间。
5. 本篇常见错排查
5.1Failed: error connecting to db server
九成是 MongoDB 服务没起。macOS 用brew services start mongodb-community,Linux 用systemctl start mongod。如果服务起了还报这个,检查端口是不是被改过,默认 27017。
5.2error validating settings: --file: invalid file path
路径问题。--file的相对路径是相对于你执行命令时所在的目录,不是相对于脚本文件。稳妥做法是用绝对路径,或者先cd到项目根目录再执行。
5.3Failed: cannot decode array into a BSON
JSON 文件是数组格式但没加--jsonArray。加上就好。反过来,如果文件是 NDJSON 却加了--jsonArray,会报解析错误,去掉即可。
5.4 导入成功但 mongoose 查不到
三个排查方向:库名不一致(mongoimport 的--db和连接串里的库名要对上);集合名不一致(--collection和 model 第三个参数要对上);连的是不同实例(比如一个连 localhost,一个连了远程)。用mongosh直接show dbs和show collections确认数据到底落在哪。
5.5 Key 读取报Unexpected token
settings.json 里有多余逗号或者用了单引号。JSON 标准不允许尾逗号和单引号,用编辑器格式化一下,或者node -e "JSON.parse(require('fs').readFileSync('config/settings.json'))"快速验证。
5.6 导入大文件时内存飙高
mongoimport默认会把整个文件读进内存解析。文件超过几百 MB 时,改用 NDJSON 格式并去掉--jsonArray,它是流式解析的,内存占用会低很多。生成 NDJSON 可以用 Node 脚本把数组拆成每行一个对象。
6. 把导入和 Key 配置收进一条流水线
到这里,一条完整的链路是:本地 JSON 用mongoimport批量灌入,mongoose 连同一个库做查询验证,TaoToken 的 Key 和 base URL 统一放在 settings.json 里供 seed 脚本和 AI 调用共用。下次换数据源,你只需要改 JSON 文件和--collection参数,配置层不用动。
如果你后面要把这套流程接到长期跑的编码任务或者 Agent 里,比如让脚本自动生成 seed 数据再导入,可以考虑用 Coding Plan 把模型调用额度固定下来,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。API Key 的生成和管理在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,接入细节看文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
最后一个实用技巧:把mongoimport命令写进 package.json 的 scripts 里,比如"seed": "mongoimport --db api --collection courses --file ./_data/courses.json --jsonArray --drop",团队里谁拉下代码都能npm run seed一键灌数据,比口头传命令靠谱得多。