[英]MongoDB- Insert if it doesn't exist, else skip
是否可以在有條件的情況下插入 Mongo;
//Pseudo code
Bulk Insert Item :
If Key exists
Skip, don't throw error
If key does not exist
Add item
如果我進行單次插入,它可能會返回錯誤或在集合中插入,但是否可以批量插入?
根據您想如何處理事情,您在這里有兩個真正的選擇:
如果關鍵數據存在,則使用 MongoDB 的upsert功能從本質上“查找”。 如果沒有,那么您只將數據傳遞給$setOnInsert
並且不會觸及其他任何內容。
批量使用“UnOrdered”操作。 即使返回錯誤,整批更新也會繼續,但錯誤報告僅此而已,任何不是錯誤的都將被提交。
整個例子:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
var testSchema = new Schema({
"_id": Number,
"name": String
},{ "_id": false });
var Test = mongoose.model('Test',testSchema,'test');
mongoose.connect('mongodb://localhost/test');
var data = [
{ "_id": 1, "name": "One" },
{ "_id": 1, "name": "Another" },
{ "_id": 2, "name": "Two" }
];
async.series(
[
// Start fresh
function(callback) {
Test.remove({},callback);
},
// Ordered will fail on error. Upserts never fail!
function(callback) {
var bulk = Test.collection.initializeOrderedBulkOp();
data.forEach(function(item) {
bulk.find({ "_id": item._id }).upsert().updateOne({
"$setOnInsert": { "name": item.name }
});
});
bulk.execute(callback);
},
// All as expected
function(callback) {
Test.find().exec(function(err,docs) {
console.log(docs)
callback(err);
});
},
// Start again
function(callback) {
Test.remove({},callback);
},
// Unordered will just continue on error and record an error
function(callback) {
var bulk = Test.collection.initializeUnorderedBulkOp();
data.forEach(function(item) {
bulk.insert(item);
});
bulk.execute(function(err,result) {
callback(); // so what! Could not care about errors
});
},
// Still processed the whole batch
function(callback) {
Test.find().exec(function(err,docs) {
console.log(docs)
callback(err);
});
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
請注意,當前驅動程序中的“更改操作”是.execute()
上的結果響應將返回一個要拋出的錯誤對象,而以前的版本在“無序”操作中沒有這樣做。
這使得您的代碼永遠不能單獨依賴於返回的err
,並且您應該檢查返回的result
而不是對錯誤進行完整分類。
盡管如此,當無序時,無論發生多少錯誤,批處理都會繼續直到結束。 不是錯誤的事情將照常提交。
這真的歸結為“序列是否重要”。 如果是這樣,那么您需要“有序”操作,並且只能通過使用“upserts”來避免重復鍵。 否則使用“無序”,但要注意錯誤返回及其實際含義。
此外,當使用.collection
從基本驅動程序獲取底層集合對象以啟用“批量”操作時,請始終確保始終首先調用“某些”貓鼬方法。
沒有它,就不能保證使用本機驅動程序方法連接到數據庫,因為它是為 mongoose 方法處理的,因此操作將由於沒有連接而失敗。
首先“觸發”mongoose 方法的替代方法是將您的應用程序邏輯包裝在連接的事件偵聽器中:
mongoose.connection.on("open",function(err) {
// app logic in here
})
正如已經說過的,“如果它不存在則插入”可以通過使用將upsert
選項設置為 true 的update
命令來實現。 以下是使用 3.x node.js 驅動程序執行此操作的方法:
let ops = [];
ops.push({ updateOne: { filter: {key:"value1"}, update: {} }, { upsert:true } });
ops.push({ updateOne: { filter: {key:"value2"}, update: { $set:{/*...*/} } }, { upsert:true } });
ops.push({ updateOne: { filter: {key:"value3"}, update: { { $setOnInsert:{/*...*/} } } }, { upsert:true } });
// < add more ops here >
await db.collection("my-collection").bulkWrite(ops, {ordered:false});
如果filter
返回零結果,將使用過濾條件和$set
更新(如果有)創建一個新文檔。 如果您使用$setOnInsert
,則更新僅適用於新文檔。
發布此示例是因為它對我的情況很方便。 db.collection.bulkWrite文檔中的更多信息。
使用setOnInsert
db.collection('collection').updateOne(
{ _id: data._id },
{ $setOnInsert: { ...data } },
{ upsert: true },
)
MongoDB 4.4 版
https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.