Skip to content

Commit 65bed62

Browse files
committed
overachieving just a lil bit
1 parent b7f0b9f commit 65bed62

1 file changed

Lines changed: 32 additions & 24 deletions

File tree

db-controller.js

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -981,26 +981,28 @@ const id = async function (req, res, next) {
981981
}
982982
}
983983

984+
/**
985+
* Create many objects at once with the power of MongoDB bulkWrite() operations.
986+
*
987+
* @see https://www.mongodb.com/docs/manual/reference/method/db.collection.bulkWrite/
988+
*/
984989
const bulkCreate = async function (req, res, next) {
985990
res.set("Content-Type", "application/json; charset=utf-8")
986991
const documents = req.body
987992
let err = {}
988-
// TODO: validate documents gatekeeper function?
989993
if (!Array.isArray(documents)) {
990994
err.message = "The request body must be an array of objects."
991-
//err.status = 406
992995
err.status = 400
993996
next(createExpressError(err))
994997
return
995998
}
996999
if (documents.length === 0) {
9971000
err.message = "No action on an empty array."
998-
//err.status = 406
9991001
err.status = 400
10001002
next(createExpressError(err))
10011003
return
10021004
}
1003-
let gatekeep = documents.filter(d=> {
1005+
const gatekeep = documents.filter(d=> {
10041006
// Each item must be valid JSON, but can't be an array.
10051007
if(Array.isArray(d) || typeof d !== "object") return d
10061008
try {
@@ -1018,6 +1020,7 @@ const bulkCreate = async function (req, res, next) {
10181020
next(createExpressError(err))
10191021
return
10201022
}
1023+
10211024
// TODO: bulkWrite SLUGS? Maybe assign an id to each document and then use that to create the slug?
10221025
// let slug = req.get("Slug")
10231026
// if(slug){
@@ -1030,10 +1033,14 @@ const bulkCreate = async function (req, res, next) {
10301033
// slug = slug_json.slug_id
10311034
// }
10321035
// }
1033-
let bulkOps = []
1034-
let generatorAgent = getAgentClaim(req, next)
1036+
1037+
// unordered bulkWrite() operations have better performance metrics.
1038+
let bulkOps = [{'ordered':false}]
1039+
const generatorAgent = getAgentClaim(req, next)
10351040
documents.forEach(d => {
1036-
const providedID = d._id
1041+
// Do not create {}
1042+
if(Object.keys(d).length === 0) continue
1043+
const providedID = d?._id
10371044
const id = isValidID(providedID) ? providedID : ObjectID()
10381045
d = utils.configureRerumOptions(generatorAgent, d)
10391046
// id is also protected in this case, so it can't be set.
@@ -1060,26 +1067,31 @@ const bulkCreate = async function (req, res, next) {
10601067
}
10611068
}
10621069

1070+
/**
1071+
* Update many objects at once with the power of MongoDB bulkWrite() operations.
1072+
* Make sure to alter object __rerum.history as appropriate.
1073+
* The same object may be updated more than once, which will create history branches (not straight sticks)
1074+
*
1075+
* @see https://www.mongodb.com/docs/manual/reference/method/db.collection.bulkWrite/
1076+
*/
10631077
const bulkUpdate = async function (req, res, next) {
10641078
res.set("Content-Type", "application/json; charset=utf-8")
10651079
const documents = req.body
10661080
let err = {}
10671081
let encountered = []
10681082
if (!Array.isArray(documents)) {
10691083
err.message = "The request body must be an array of objects."
1070-
//err.status = 406
10711084
err.status = 400
10721085
next(createExpressError(err))
10731086
return
10741087
}
10751088
if (documents.length === 0) {
10761089
err.message = "No action on an empty array."
1077-
//err.status = 406
10781090
err.status = 400
10791091
next(createExpressError(err))
10801092
return
10811093
}
1082-
let gatekeep = documents.filter(d => {
1094+
const gatekeep = documents.filter(d => {
10831095
// Each item must be valid JSON, but can't be an array.
10841096
if(Array.isArray(d) || typeof d !== "object") return d
10851097
try {
@@ -1090,24 +1102,24 @@ const bulkUpdate = async function (req, res, next) {
10901102
// Items must have an @id, or in some cases an id will do
10911103
const idcheck = _contextid(d["@context"]) ? d.id ?? d["@id"] : d["@id"]
10921104
if(!idcheck) return d
1093-
})
1105+
})
1106+
// The empty {}s will cause this error
10941107
if (gatekeep.length > 1) {
10951108
err.message = "All objects in the body of a `/bulkUpdate` must be JSON and must contain a declared identifier property."
10961109
err.status = 400
10971110
next(createExpressError(err))
10981111
return
10991112
}
1100-
let bulkOps = []
1101-
let generatorAgent = getAgentClaim(req, next)
1113+
// unordered bulkWrite() operations have better performance metrics.
1114+
let bulkOps = [{'ordered':false}]
1115+
const generatorAgent = getAgentClaim(req, next)
11021116
for(const objectReceived of documents){
11031117
// We know it has an id
11041118
const idReceived = objectReceived["@id"] ?? objectReceived.id
1105-
// but we will not update the same thing twice.
1106-
if(encountered.includes(idReceived)) continue
1119+
// Update the same thing twice? can vs should.
1120+
// if(encountered.includes(idReceived)) continue
11071121
encountered.push(idReceived)
1108-
if(!idReceived.includes(process.env.RERUM_ID_PREFIX)){
1109-
continue
1110-
}
1122+
if(!idReceived.includes(process.env.RERUM_ID_PREFIX)) continue
11111123
let id = parseDocumentID(idReceived)
11121124
let originalObject
11131125
try {
@@ -1116,12 +1128,8 @@ const bulkUpdate = async function (req, res, next) {
11161128
next(createExpressError(error))
11171129
return
11181130
}
1119-
if (null === originalObject) {
1120-
continue
1121-
}
1122-
if (utils.isDeleted(originalObject)) {
1123-
continue
1124-
}
1131+
if (null === originalObject) continue
1132+
if (utils.isDeleted(originalObject)) continue
11251133
id = ObjectID()
11261134
let context = objectReceived["@context"] ? { "@context": objectReceived["@context"] } : {}
11271135
let rerumProp = { "__rerum": utils.configureRerumOptions(generatorAgent, originalObject, true, false)["__rerum"] }

0 commit comments

Comments
 (0)