существует ли какая-либо агрегатная или массовая операция, которая может сделать эту операцию проще / быстрее
Вы можете запустить MongoDB Агрегационный конвейер , чтобы обработать поиск и замену, затем выполнить итерацию по результату и отправить неупорядоченные операции массового обновления .
Я напишу приведенные ниже примеры в mongo shell , чтобы сделать его обобщенным, но для Mongoose эквивалента, пожалуйста, смотрите - Model.aggregate () и Model.bulkWrite () для получения дополнительной информации.
Например, если у вас есть три документа, как показано ниже:
{ "_id": 1, "path": "a,b,c,d" }
{ "_id": 2, "path": "b,a,c,d" }
{ "_id": 3, "path": "c,b,a" }
Где вы хотели бы заменить a
на 1,2,3
. Используя конвейер агрегации, создайте новое поле с именем newPath
для хранения замещенного результата, как показано ниже:
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,
}}
])
Это выведет что-то, как показано ниже:
{ "_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" }
Обратите внимание, что приведенная выше агрегация написана так, чтобы ее можно было повторно использовать для другой замены. то есть заменили toBeRemoved
на b
и replacement
на x,y
, и это будет работать аналогично.
Приведенный выше конвейер агрегации должен работать для MongoDB v3.4 +. Также стоит отметить, что в настоящее время существует открытый билет SERVER-11947 для добавления поддержки регулярных выражений в язык агрегации.
Затем можно выполнить итерацию по результату и отправить неупорядоченные bulkWrite
операции обновления, например, ниже:
db.collection.bulkWrite(
[
{ "updateOne" :
{
"filter" : { "_id" : 1},
"update" : { "$set" : { "path" : <newPath value> } }
}
},
{ "updateOne" :
{
"filter" : { "_id" : 2},
"update" : { "$set" : { "path" : <newPath value> } }
}
},
)