使用 mongoose 在 MongoDB 中批量插入多个集合

Posted

技术标签:

【中文标题】使用 mongoose 在 MongoDB 中批量插入多个集合【英文标题】:Bulk insert in MongoDB with mongoose for multiple collections 【发布时间】:2018-03-24 02:45:30 【问题描述】:

我有 2 个收藏(datametaData

data 架构是


_id: ......,
name: ......, //not unique
mobile: ......, // unique or null
email: ......, // unique or null
uniqueId: ......, // unique or null

插入需要至少一个唯一数据

metaData 架构是


_id: ......,
dataId: ......,//refrence from _id of data collection
key: ......,
value: ......

JSON 数组正在从客户端获取

[
  name: "abc",
  mobile: 9999999999,
  mData: 
    c1: 123,
    c2: "xyz"
  
,

  name: "qwerty",
  email: 'qwerty@mail.com',
  mData: 
    c1: 123,
    c2: "zxc"
  

......
]

我正在遍历数组并将它们中的每一个都插入到 MongoDB 中。

let Bulk = Data.collection.initializeUnorderedBulkOp();
dataArr.forEach(function(item) 
  let data = service.generateData(item);
  // data.query: mobile: ..., email: ..., uniqueId: ...
  // if value exists then keys is also exists for mobile, email, uniqueId in query
  Bulk.find(data.query).upsert().updateOne(data.doc);
);
Bulk.execute((e, d) => 
  let metaBulk = MetaData.collection.initializeOrderedBulkOp();
  let length = dataArr.length;
  dataArr.forEach(function(data) 
    Data.findOne(data.query).exec(function(err, data) 
      length--;      
      for(let key in data["mData"]) 
        let value = data["mData"][key] || "";
        let mData = service.generateMdata(key, value, data._id);
        metaBulk.find(mData.query).upsert().updateOne(mData.doc);
      
      if(length == 0) 
        metaBulk.execute();
      
    );
  );
);

我的解决方案目前运行良好,但迭代 data 集合以查找 metaData 集合的 ID 需要花费大量时间。

我需要一种将数据批量插入 MongoDB 的方法,而无需查找数据 ID 查询。是否有任何选项可以在单个查询中使用 mongoose 为多个集合执行批量更新。

【问题讨论】:

每个数组项的数据不是唯一的吗?如果是这样,那么为什么不简单地应用每个数组中已经唯一的标识符呢?看起来您正在抽象,实际上您的“客户”实际上已经为您提供了唯一标识的项目。所以你真正的问题是让驱动程序为 _id 分配一个值,而你应该使用客户端提供的值。 是否可以将所有信息仅移动到一个集合中?那么元数据元素会简单地变成数据文档中的数组吗?这更像是一种文档存储类型的设计。如果可能,您应该避免使用任何连接概念。 @NeilLunn 数组中的所有数据都是唯一的,但有一些键,我已经根据真实数据更新了我的问题。所以它包含多个具有空或唯一数据的列。 @dnickless 没有将所有信息移到一个集合中的选项。 你还没有真正解决任何被评论的问题。如果您仔细阅读,那么您应该看到“upsert”的概念意味着数据中的某些内容需要被在.find() 中查找它的查询视为“唯一”。因此,您的查询条件确实已经确定了“唯一键”。您的整个问题都围绕着找到“插入”的_id 值。您只需使用“已经唯一”的数据作为该值来解决问题,而不是等待驱动程序分配它。这是一个非常简单的概念。 【参考方案1】:

对于您的场景,单个命令中没有多个集合更新。在您的情况下,如果您可以在父集合中包含元数据数组,它可以使用带有 updateMany() 的单个命令插入数据。 MongoDB 还支持通过db.collection.insertMany() 进行批量插入。

db.data.insertMany( [ name: "abc",mobile: 9999999999, mData:  c1: 123, c2: "xyz" ,
                                            name: "qwerty",email: 'qwerty@mail.com',mData:  c1: 123, c2: "zxc" ]);

您也可以使用db.collection.bulkWrite()。

【讨论】:

【参考方案2】:

我认为你可以做的是:

async.each(jsonArray, function(jsonData,callback)
  //first insert data in data schema
  var data = new data(jsonData);
  data.save(function(err)
    if err throw err;
    //then you save the data in metaData collection
    async.each(jsonData.mData, function(metadata, callback2)
      var metaDataObj = new metaData(metadata);
      metaDataObj.dataId = data._id;
      metaDataObj.save(function(err)
       callback2();
      );
    , function(err, results1)
      callback();
    );
  );
, function(err, results)
   console.log('Data is saved');
);

【讨论】:

不是大数据批量操作的相对答案

以上是关于使用 mongoose 在 MongoDB 中批量插入多个集合的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以使用 mongoose 从 mongodb 批量操作中获取修改后的 IDS?

Mongoose (mongodb) 批量插入、删除、更新和无操作

mongoose 批量操作

Mongoose 批量插入子类别

Mongoose:批量更新插入,但仅在满足某些条件时才更新记录

猫鼬批量插入错误