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

4
我有两个集合(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在单个查询中执行多个集合的批量更新选项?

1
每个数组项的数据不是已经唯一了吗?如果是这样,为什么不直接应用每个数组中已经唯一的标识符呢?看起来你正在抽象化,实际上你的“客户端”已经提供了唯一标识的项目。因此,你真正的问题是让驱动程序为“_id”分配一个值,而你应该使用客户端提供的值。 - Neil Lunn
1
把所有信息都移入一个集合中是个好主意吗?这样元数据元素就会变成数据文档内的数组。这将更符合文档存储的设计。如果可能的话,应该避免任何联接概念。 - dnickless
1
你并没有真正解决任何被评论的问题。如果你仔细阅读,你应该能看到"upsert"的概念意味着数据中的某些内容需要被查询中的.find()视为"唯一"。因此,你的查询条件已经确定了一个"唯一键"。你整个问题的关键在于找到被"upserted"的_id值。你可以通过使用"已经唯一"的数据作为该值来解决这个问题,而不是等待驱动程序分配它。这是一个非常简单的概念。 - Neil Lunn
{btsdaf} - Gaurav Kumar Singh
{btsdaf} - Gaurav Kumar Singh
显示剩余8条评论
2个回答

2
您的情况下无法使用单个命令进行多个集合更新。如果您可以在父级集合中包含元数据数组,就可以通过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');
});

不是针对大数据批量操作的相关答案。 - Gaurav Kumar Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接