使用正则表达式在Mongo中查找和替换

时间:2019-01-17 17:13:35

标签: mongodb mongoose mongodb-query

我在Mongo中有一个形状如下的集合:

  {
    path: 'any string', // e.g., 'a,b,c,d,e'
  }

我需要在此集合中的所有文档中找到'a'并将其替换为另一个字符串,例如'1,2,3'。我知道可以使用find(),遍历结果并更新数据库中的结果来非常低效地完成此操作。是否有某种合计或批量操作可以使此操作更容易/更快(我正在使用Mongoose)?谢谢

1 个答案:

答案 0 :(得分:2)

  

是否存在某种汇总或批量操作,可以使此操作更容易/更快

您可以运行MongoDB Aggregation Pipeline来处理查找和替换,然后遍历结果并发送unordered bulk update operations

我将在mongo shell中编写以下示例以使其具有通用性,但对于等效的Mongoose,请参见-Model.aggregate()Model.bulkWrite()以获取更多信息。

例如,如果您有以下三个文档:

a.target = '_blank'

要将{ "_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,它的工作原理类似。

上面的聚合管道应适用于MongoDB v3.4 +。还值得一提的是,目前有一个开放票证SERVER-11947,可为聚合语言添加正则表达式支持。

然后您可以遍历结果,并发送无序的x,y更新操作,如下例:

bulkWrite