Mongoose/MongoDB:如何将已有文档推入另一文档的数组中
问题:无法将hosts数组追加到MongoDB文档的hosts属性中
我尝试将一个文档的hosts数组追加到另一个Scan文档的hosts属性里,但始终无法成功。使用Model.findOneAndUpdate和$push操作符时没有抛出错误,但目标扫描文档并未更新。
Schema定义
const ScanSchema = new Schema({ date: { type: Date }, hosts: [{ type: Schema.Types.ObjectId, ref: "Host" }], });
待追加的hostsToAdd内容
[{ status: { state: 'up', reason: 'user-set', reason_ttl: '0', change_detection_color: 'red' }, address: { addr: '', addrtype: 'ipv4' }, times: { starttime: '', endtime: '', smoothed_rtt: '', rtt_variance: '', timeout: '' }, _id: new ObjectId("63ea1cf7a7efd5be803e5ea4"), hostnames: [ '\n' ], ports: [ [Object], [Object] ], __v: 0 }]
尝试的代码
let update = { "$push": { "hosts": hostsToAdd, } } Scan.findOneAndUpdate(update, {returnNewDocument: true}) .sort('-date') .populate('hosts') .exec()
解决方案
你的代码存在几个关键问题,修正后即可实现需求:
1. 修正findOneAndUpdate参数顺序
findOneAndUpdate第一个参数是查询条件(匹配要更新的文档),第二个参数才是更新操作。你之前把更新操作当作查询条件,导致没有匹配到目标文档,自然不会执行更新。
2. 用$each批量追加数组元素
hostsToAdd是数组,直接$push会把整个数组作为单个元素塞入hosts。配合$each修饰符,才能将数组内的每个元素逐个追加到目标数组中。
3. 只传递ObjectId符合Schema定义
ScanSchema的hosts字段存储的是Host文档的ObjectId引用,不需要传递完整host对象,只需要提取每个host的_id即可。
4. 替换returnNewDocument为new: true
returnNewDocument是MongoDB原生驱动选项,Mongoose中推荐使用new: true来返回更新后的文档。
修正后的代码
// 查询条件:匹配最新的Scan文档(按date倒序) const query = {}; // 更新操作:用$each批量追加host的ObjectId const update = { "$push": { "hosts": { "$each": hostsToAdd.map(host => host._id) } } }; // 配置选项:返回更新后的文档,按date倒序定位目标文档 const options = { new: true, sort: { date: -1 } }; // 执行更新并处理结果 Scan.findOneAndUpdate(query, update, options) .populate('hosts') .exec() .then(updatedScan => { console.log('更新后的文档:', updatedScan); }) .catch(err => { console.error('更新失败:', err); });
内容的提问来源于stack exchange,提问作者crispy
相关产品推荐
相关产品推荐

