使用mongosh与Ubuntu Bash修改MongoDB文档并插入的问题
问题解决与最优方案
1. jq报错原因与修复
你遇到的「parse error: Invalid numeric literal」错误,本质是jq不支持MongoDB的扩展JSON格式(比如ISODate("2024-05-20T12:34:56.123456789Z")这种非标准JSON语法)。即使你验证的是标准JSON,只要文档里包含MongoDB特有的BSON类型表示(纳秒级ISODate、ObjectId等),jq就会解析失败。
如果一定要用jq处理,需要先做格式转换:
- 导出文档时用
mongosh --eval 'JSON.stringify(db.collection.findOne())'(把ISODate转成标准字符串格式) - 用jq修改字段:
# 假设原始文档存于doc.json jq '.["creation-date"] = "2024-05-20T12:34:56.123456789Z" | .environment = "prod" | .fileName = (.fileName | split(".")[0])' doc.json > modified_doc.json - 导入时再解析为BSON类型:
mongosh --eval 'db.collection.insertOne(EJSON.parse(cat("modified_doc.json")))'
2. insertOne调用方式纠正
你用insertOne(EJSON.stringify($newDocument))是错误的:
EJSON.stringify()会把JS对象转成JSON字符串,而insertOne()需要的是BSON文档对象,不是字符串。这样插入后,整个文档会被存成一个字符串字段,而非结构化的BSON文档。- 正确写法:
- 如果
$newDocument是mongosh里的JS对象,直接传:db.collection.insertOne($newDocument) - 如果是从外部JSON字符串获取,先解析:
db.collection.insertOne(EJSON.parse(jsonString))
- 如果
3. 最优操作方案(无需jq,直接用mongosh)
既然已经在mongosh环境下获取了文档,直接在JS环境里修改字段是最高效的,避免格式转换问题:
单文档处理步骤示例
- 获取目标文档:
let doc = db.your_collection.findOne({/* 你的查询条件 */}); - 修改三个字段:
- 纳秒级creation-date:直接用
new Date()生成带纳秒的ISODate,或解析指定字符串:doc["creation-date"] = new Date("2024-05-20T12:34:56.123456789Z"); // 若要设置当前时间(自动带纳秒): doc["creation-date"] = new Date(); - environment字段:直接赋值:
doc.environment = "production"; // 替换为你的目标值 - 截取fileName子串:用JS字符串方法处理,比如取第一个
.前的部分:// 示例:fileName为"report_2024.pdf",截取后为"report_2024" doc.fileName = doc.fileName.split(".")[0]; // 按其他规则截取(如从第3位到第10位): doc.fileName = doc.fileName.slice(2, 10);
- 纳秒级creation-date:直接用
- 插入或更新文档:
- 插入新文档:
db.your_collection.insertOne(doc); - 更新原文档:
db.your_collection.updateOne({_id: doc._id}, {$set: { "creation-date": doc["creation-date"], environment: doc.environment, fileName: doc.fileName }});
- 插入新文档:
批量处理/脚本化场景
如果需要批量处理或从外部文件读取文档,可编写mongosh脚本文件(如modify_docs.js):
// modify_docs.js const docs = db.your_collection.find({/* 查询条件 */}).toArray(); docs.forEach(doc => { // 修改字段 doc["creation-date"] = new Date(); doc.environment = "staging"; doc.fileName = doc.fileName.split("-")[1]; // 自定义截取规则 // 插入新文档或更新原文档 db.your_collection.insertOne(doc); // 或更新:db.your_collection.updateOne({_id: doc._id}, {$set: doc}); });
在bash中执行脚本:
mongosh your_database modify_docs.js
内容的提问来源于stack exchange,提问作者Observer
相关产品推荐
相关产品推荐

