Найти и заменить в Монго с помощью регулярных выражений

В 1-м, 2-м и третьем выпусках ECMAScript использование переменных $ -prefixed переменных явно не поощрялось спецификацией, за исключением контекста автогенерированного кода:

Знак доллара ($) и символ подчеркивания (_) разрешены в любом месте идентификатора. Знак доллара предназначен для использования только в механически сгенерированном коде.

blockquote>

Однако в следующей версии ([1] 5th Edition , которая является текущей), это ограничение было , а приведенный выше фрагмент заменен на

Знак доллара ($) и знак подчеркивания (_) разрешены в любом месте в IdentifierName .

blockquote>

Таким образом, знак $ теперь может свободно использоваться в именах переменных. Определенные структуры и библиотеки имеют свои собственные условные обозначения о значении символа, отмеченные в других ответах здесь.

0
задан bgmaster 17 January 2019 в 17:13
поделиться

1 ответ

есть какая-то агрегированная или групповая операция, которая может сделать эту операцию проще / быстрее

Вы можете запустить MongoDB Aggregation Pipeline для обработки поиска и заменить, затем перебрать результат и отправить неупорядоченные операции массового обновления .

Я напишу приведенные ниже примеры в 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> } }
          }
       }, 
)
0
ответ дан Wan Bachtiar 17 January 2019 в 17:13
поделиться