You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Node.js的Mongoose中插入/更新JSON数组及批量插入?

在Mongoose中实现批量插入/更新的方案

嘿,你提到的需求Mongoose完全能搞定!不管是批量插入全新数据,还是批量做「存在就更新、不存在就插入」(也就是Upsert)的操作,都有对应的方法,我结合你的JSON数组给你具体讲讲:

1. 批量插入全新数据

如果你的数组里全是新数据(没有和数据库中现有文档重复的记录),直接用Model.insertMany()就可以,这是Mongoose专门用来批量插入的高效方法。

步骤示例:

首先得先定义对应的Schema和Model(假设你的集合叫products):

const mongoose = require('mongoose');

const productSchema = new mongoose.Schema({
  art: String,
  count: Number, // 注意:你的count是字符串,建议转成数字类型存储更合理
  name: String,
  ean: { type: String, unique: true }, // 把ean设为唯一键,避免重复插入
  marker: mongoose.Schema.Types.Mixed, // 或者直接设为String,根据实际业务需求调整
  stammkost: String
});

const Product = mongoose.model('Product', productSchema);

然后在你的POST接口里处理请求:

// 假设是Express的路由处理函数
app.post('/products/batch', async (req, res) => {
  try {
    // 先预处理数据:把count转成数字,把"null"字符串转成真实的null值
    const processedData = req.body.map(item => ({
      ...item,
      count: parseInt(item.count, 10),
      marker: item.marker === "null" ? null : item.marker
    }));

    // 执行批量插入
    const result = await Product.insertMany(processedData);
    res.status(201).json({
      message: '批量插入成功',
      insertedCount: result.length
    });
  } catch (err) {
    // 如果有重复的ean(因为设了unique索引),会触发DuplicateKeyError
    if (err.code === 11000) {
      res.status(400).json({ message: '存在重复的EAN码,请检查数据' });
    } else {
      res.status(500).json({ message: '插入失败', error: err.message });
    }
  }
});

2. 批量Upsert(插入或更新)

如果你的数据里可能有已存在的记录(比如ean已经在数据库里了),需要实现「存在就更新,不存在就插入」,这时候要用Model.bulkWrite()方法,它支持批量执行多种数据库操作。

核心思路:

对数组里的每一个元素,创建一个updateOne操作:

  • ean作为匹配条件(因为ean是商品唯一标识,适合用来判断记录是否存在)
  • 设置upsert: true,表示没有匹配到就插入新文档
  • $set来更新已存在的字段,若有只在插入时才需要设置的字段,可以用$setOnInsert

代码示例:

app.post('/products/batch-upsert', async (req, res) => {
  try {
    // 预处理数据,统一格式
    const processedData = req.body.map(item => ({
      ...item,
      count: parseInt(item.count, 10),
      marker: item.marker === "null" ? null : item.marker
    }));

    // 构建bulkWrite的操作数组
    const bulkOperations = processedData.map(item => ({
      updateOne: {
        filter: { ean: item.ean }, // 用ean匹配现有文档
        update: {
          $set: {
            art: item.art,
            count: item.count,
            name: item.name,
            marker: item.marker,
            stammkost: item.stammkost
          }
          // 示例:如果有插入时才需要设置的字段,比如创建时间
          // $setOnInsert: { createdAt: new Date() }
        },
        upsert: true // 关键配置:没有匹配到就插入新文档
      }
    }));

    // 执行批量Upsert操作
    const result = await Product.bulkWrite(bulkOperations);

    res.status(200).json({
      message: '批量Upsert完成',
      insertedCount: result.insertedCount,
      updatedCount: result.modifiedCount
    });
  } catch (err) {
    res.status(500).json({ message: 'Upsert失败', error: err.message });
  }
});

注意点:

  • 一定要确保用来匹配的字段(比如这里的ean)有唯一索引,不然可能会出现重复文档
  • bulkWrite的返回结果里会包含insertedCount(插入的新文档数)和modifiedCount(更新的现有文档数),可以用来做操作统计
  • 预处理数据很关键:你的原始数据里count是字符串、marker是"null"字符串,这些都要转成数据库里合适的类型,避免后续查询或计算出问题

内容的提问来源于stack exchange,提问作者Hamed Rahmani

火山引擎 最新活动