U wilt in feite bulkWrite()
, die de invoerarray van objecten kan gebruiken en deze kan gebruiken om een "batch" verzoeken te doen om de overeenkomende documenten bij te werken.
Ervan uitgaande dat de reeks documenten wordt verzonden in req.body.updates
, dan zou je zoiets hebben als
const Model = require('../models/model');
router.post('/update', (req,res) => {
Model.bulkWrite(
req.body.updates.map(({ slno, name }) =>
({
updateOne: {
filter: { slno },
update: { $set: { name } }
}
})
)
})
.then(result => {
// maybe do something with the WriteResult
res.send("ok"); // or whatever response
})
.catch(e => {
// do something with any error
})
})
Dit stuurt een verzoek met de invoer als:
bulkWrite([
{ updateOne: { filter: { slno: 1 }, update: { '$set': { name: 'Item 3' } } } },
{ updateOne: { filter: { slno: 2 }, update: { '$set': { name: 'Item 1' } } } },
{ updateOne: { filter: { slno: 3 }, update: { '$set': { name: 'Item 2' } } } } ]
)
Die alle updates efficiënt uitvoert in een enkel verzoek aan de server met een enkel antwoord.
Zie ook de kerndocumentatie van MongoDB op bulkWrite()
. Dat is de documentatie voor de mongo
shell-methode, maar alle opties en syntaxis zijn precies hetzelfde in de meeste stuurprogramma's en vooral in alle op JavaScript gebaseerde stuurprogramma's.
Als een volledig werkende demonstratie van de methode die wordt gebruikt met mangoest:
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.Promise = global.Promise;
mongoose.set('debug',true);
const testSchema = new Schema({
slno: Number,
name: String
});
const Test = mongoose.model('Test', testSchema);
const log = data => console.log(JSON.stringify(data, undefined, 2));
const data = [1,2,3].map(n => ({ slno: n, name: `Item ${n}` }));
const request = [[1,3],[2,1],[3,2]]
.map(([slno, n]) => ({ slno, name: `Item ${n}` }));
mongoose.connect(uri)
.then(conn =>
Promise.all(Object.keys(conn.models).map( k => conn.models[k].remove()))
)
.then(() => Test.insertMany(data))
.then(() => Test.bulkWrite(
request.map(({ slno, name }) =>
({ updateOne: { filter: { slno }, update: { $set: { name } } } })
)
))
.then(result => log(result))
.then(() => Test.find())
.then(data => log(data))
.catch(e => console.error(e))
.then(() => mongoose.disconnect());
Of voor modernere omgevingen met async/await
:
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.Promise = global.Promise;
mongoose.set('debug',true);
const testSchema = new Schema({
slno: Number,
name: String
});
const Test = mongoose.model('Test', testSchema);
const log = data => console.log(JSON.stringify(data, undefined, 2));
const data = [1,2,3].map(n => ({ slno: n, name: `Item ${n}` }));
const request = [[1,3],[2,1],[3,2]]
.map(([slno,n]) => ({ slno, name: `Item ${n}` }));
(async function() {
try {
const conn = await mongoose.connect(uri)
await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));
await Test.insertMany(data);
let result = await Test.bulkWrite(
request.map(({ slno, name }) =>
({ updateOne: { filter: { slno }, update: { $set: { name } } } })
)
);
log(result);
let current = await Test.find();
log(current);
mongoose.disconnect();
} catch(e) {
console.error(e)
} finally {
process.exit()
}
})()
Die de initiële gegevens laadt en vervolgens bijwerkt, waarbij het antwoordobject ( geserialiseerd ) en de resulterende items in de verzameling worden weergegeven nadat de update is verwerkt:
Mongoose: tests.remove({}, {})
Mongoose: tests.insertMany([ { _id: 5b1b89348f3c9e1cdb500699, slno: 1, name: 'Item 1', __v: 0 }, { _id: 5b1b89348f3c9e1cdb50069a, slno: 2, name: 'Item 2', __v: 0 }, { _id: 5b1b89348f3c9e1cdb50069b, slno: 3, name: 'Item 3', __v: 0 } ], {})
Mongoose: tests.bulkWrite([ { updateOne: { filter: { slno: 1 }, update: { '$set': { name: 'Item 3' } } } }, { updateOne: { filter: { slno: 2 }, update: { '$set': { name: 'Item 1' } } } }, { updateOne: { filter: { slno: 3 }, update: { '$set': { name: 'Item 2' } } } } ], {})
{
"ok": 1,
"writeErrors": [],
"writeConcernErrors": [],
"insertedIds": [],
"nInserted": 0,
"nUpserted": 0,
"nMatched": 3,
"nModified": 3,
"nRemoved": 0,
"upserted": [],
"lastOp": {
"ts": "6564991738253934601",
"t": 20
}
}
Mongoose: tests.find({}, { fields: {} })
[
{
"_id": "5b1b89348f3c9e1cdb500699",
"slno": 1,
"name": "Item 3",
"__v": 0
},
{
"_id": "5b1b89348f3c9e1cdb50069a",
"slno": 2,
"name": "Item 1",
"__v": 0
},
{
"_id": "5b1b89348f3c9e1cdb50069b",
"slno": 3,
"name": "Item 2",
"__v": 0
}
]
Dat maakt gebruik van syntaxis die compatibel is met NodeJS v6.x