需求

mongoDB是没有定义replace函数的,那么,如果有需求需要替换nongo中数据的某一部分,怎么办?因为mongo的shell其实就是个js脚本执行器,因此,js其实是可以执行的,因此,我们可以在精准查询到需要执行replace的地方的基础上,用js实现replace。
我遇到的需求是,替换掉所有mongo中domain字段中,以Caleb开头的,全部替换为go/trend。

查询

首先,需要先能查询到所有domain字段的位置,因为我的mongo结构比较复杂,数组嵌套数组,因此,我这里需要复杂查询。复杂查询语句的详细讲解请参考我上篇博客:mongo复杂查询,嵌套多层数组和正则表达式
这是我的查询语句:
datasource数组下面的stct,stct下面的views数组,views数组下的metricView,metricView下的domain字段,要求以caleb开头,用正则表达式实现:

db.getCollection('richPage').find({"dataSources":{$elemMatch:{"stct.views":{$elemMatch:{"metricView.domain":{$regex:"Caleb",$options:"$i"}}}}}})

replace

在先能精准定位并查询到需要改动的字段的基础上,就可以执行replace操作了,直接上脚本,再慢慢解释:

db.getCollection('richPage').find({"dataSources":{$elemMatch:{"stct.views":{$elemMatch:{"metricView.domain":{$regex:"Caleb",$options:"$i"}}}}}}).forEach( 
 function(item) {
  var dataSource = item['dataSources'];
  for(var i in dataSource){
    var stct = dataSource[i]['stct'];
    if(stct != null){
     var views = stct['views'];
    if(views != null){
     for(var j in views){
      var domain = views[j]['metricView']['domain'];
      var domainUid = views[j]['metricView']['domainUid'];
      if(domain != null && String(domain).search('Caleb') > -1){
          domain = domain.replace('Caleb', 'Go/Trends');
          domainUid = domainUid.replace('caleb', 'go/trends');
          views[j]['metricView']['domain'] = domain;
          views[j]['metricView']['domainUid'] = domainUid;
        }
      }
    }
}
  }db.getCollection('richPage').updateOne({"_id":item['_id']},{$set:{"dataSources":dataSource,"exec":1}});
  }
 );

因为mongo是没有replace函数的,又因为mongo的shell解释器其实是个js解释器,因此,js是可以用的,那么:
.forEach:就是对查询到的结果,进行遍历
item:就是遍历到的每一个结果集
item[‘dataSources’]:通过中括号的方式拿数据(这里需要特殊说明一下,mongo的shell脚本版本不一样,取值方式也可能有差别,我这里的是js脚本中的方式,亲测可以成功取值)
var domain:用var接收数据后,用js中的replace方法替换需要改动的地方,然后再重新赋值:views[j][‘metricView’][‘domain’] = domain
“_id”:item[‘_id’]:就是选中要更新的item
“dataSources”:dataSource":这里dataSource在js中已经被重新赋值了,我们需要replace的字段包含在dataSource中,因此更新这个属性就行,当然也可以是别的,只要能包含你所有的改动就行

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐