is there some sort of aggregate or bulk operation that can make this operation easier/faster
You could run MongoDB Aggregation Pipeline to process the find and replace, then iterate through the result and send unordered bulk update operations.
I'll write the examples below in mongo shell to keep it generic, but for Mongoose equivalent please see - Model.aggregate() and Model.bulkWrite() for more information.
For example, if you have three documents as below:
{ "_id": 1, "path": "a,b,c,d" }
{ "_id": 2, "path": "b,a,c,d" }
{ "_id": 3, "path": "c,b,a" }
Where you would like to replace a with 1,2,3. Using aggregation pipeline, create a new field called newPath to store the substituted result, as below:
db.collection.aggregate([
{"$addFields":{
"toBeRemoved": "a",
"replacement": "1,2,3",
}},
{"$addFields":{
"newPath": {
"$concat":[
{"$substrBytes":[
"$path",
0,
{ "$cond": {
"if": {
"$lt": [ {"$subtract": [{"$strLenBytes": "$path"}, {"$subtract": [ {"$strLenBytes": "$path"}, {"$indexOfBytes":["$path", "$toBeRemoved"]} ] } ]}, 0]
},
"then": 0,
"else": {"$subtract": [{"$strLenBytes": "$path"}, {"$subtract": [ {"$strLenBytes": "$path"}, {"$indexOfBytes":["$path", "$toBeRemoved"]} ] } ]}
}
}]},
"$replacement",
{"$substrBytes":[
"$path",
{"$add":[{
"$cond": {
"if": {
"$lt": [ {"$subtract": [{"$strLenBytes": "$path"}, {"$subtract": [ {"$strLenBytes": "$path"}, {"$indexOfBytes":["$path", "$toBeRemoved"]} ] } ]}, 0]
},
"then": 0,
"else": {"$subtract": [{"$strLenBytes": "$path"}, {"$subtract": [ {"$strLenBytes": "$path"}, {"$indexOfBytes":["$path", "$toBeRemoved"]} ] } ]}
}
}, {"$strLenBytes": "$toBeRemoved"}
]},
{"$subtract": [
{"$strLenBytes": "$path"},
{"$add": [
{"$indexOfBytes":["$path", "$toBeRemoved"]},
{"$strLenBytes": "$toBeRemoved"}
]}
]}
]}
]
},
}},
{"$project": {
"toBeRemoved":0,
"replacement":0,
}}
])
This will output something as below:
{ "_id": 1, "path": "a,b,c,d", "newPath": "1,2,3,b,c,d" }
{ "_id": 2, "path": "b,a,c,d", "newPath": "b,1,2,3,c,d" }
{ "_id": 3, "path": "c,b,a", "newPath": "c,b,1,2,3" }
Please note that the aggregation above has been written so that it can be re-used for other substitution. i.e. replaced toBeRemoved with b and replacement with x,y and it would work similarly.
The aggregation pipeline above should work for MongoDB v3.4+. Also worth mentioning that currently there's an open ticket SERVER-11947 to add regex support to the aggregation language.
You can then iterate through the result, and send unordered bulkWrite update operations, with an example below:
db.collection.bulkWrite(
[
{ "updateOne" :
{
"filter" : { "_id" : 1},
"update" : { "$set" : { "path" : <newPath value> } }
}
},
{ "updateOne" :
{
"filter" : { "_id" : 2},
"update" : { "$set" : { "path" : <newPath value> } }
}
},
)