【问题标题】:Copy MongoDb indexes between databases在数据库之间复制 MongoDb 索引
【发布时间】:2023-03-29 01:08:01
【问题描述】:

我正在尝试在两个环境之间复制 mongo 索引。检查API,发现没有直接的方法。所以我开始编写一个脚本,连接到一个数据库,遍历集合,抓取索引,改变它们(因为getIndexes()ensureIndex()具有不同的格式),连接到另一个数据库,擦除索引并复制新的里面的。

这一切都感觉有点过头了,所以我想我一定是错过了什么。

有什么建议/好的做法吗?除了拥有索引创建策略。

干杯!

【问题讨论】:

  • 一次性似乎是合理的,因为您将来可能会有一个索引创建策略。 :)

标签: mongodb indexing


【解决方案1】:

请在要复制索引的数据库上运行。

db.getCollectionNames().forEach(function(collection) {
indexes = db[collection].getIndexes();
indexes.forEach(function (c) {
opt = ''
ixkey = JSON.stringify(c.key, null, 1).replace(/(\r\n|\n|\r)/gm,"")
ns = c.ns.substr(c.ns.indexOf(".") + 1, c.ns.length)
for (var key in c) {
 if (key != 'key' && key != 'ns' && key != 'v') {
 if (opt != '') { opt+= ','}        
 if (c.hasOwnProperty(key)) {
   if (typeof(c[key]) == "string") {
        opt +=  (key + ': "' + c[key] + '"')
      } else  {
        opt+=  (key + ": " + c[key])
       }
     }
   }
  }
  if (opt != '') { opt = '{' + opt + '}'}
  print ('db.' + ns + '.ensureIndex(' + ixkey + ','+  opt + ')')
 })});

【讨论】:

    【解决方案2】:

    我已经更新了 Adamo Tonete 的脚本

    db.getCollectionNames().forEach(function(col) {
        var indexes = db[col].getIndexes();
        indexes.forEach(function (c) {
            var fields = '', result = '', options = {};
            for (var i in c) {
                if (i == 'key') {
                    fields = c[i];
                } else if (i == 'name' && c[i] == '_id_') {
                    return;
                } else if (i != 'name' && i != 'v' && i != 'ns') {
                    options[i] = c[i];
                }
            }
            var fields = JSON.stringify(fields);
            var options = JSON.stringify(options);
            if (options == '{}') {
                result = "db." + col + ".createIndex(" + fields + "); ";
            } else {
                result = "db." + col + ".createIndex(" + fields + ", " + options + "); ";
            }
            result = result
                .replace(/{"floatApprox":-1,"top":-1,"bottom":-1}/ig, '-1')
                .replace(/{"floatApprox":(-?\d+)}/ig, '$1')
                .replace(/\{"\$numberLong":"(-?\d+)"\}/ig, '$1');
            print(result);
        });
    });
    

    【讨论】:

      【解决方案3】:

      这是一个使用选项重新创建它们的版本,并且使用新的 createIndex 命令而不是 ensureIndex(从 mongoDB 3.0 开始)。这样,就可以很容易地将所有索引从一个数据库复制(重新创建)到另一个数据库。

      function createIndex2( coll, keys, options ) {
          var ret = db[coll].createIndex(keys, options)
          if (ret.createdCollectionAutomatically) print( "Collection " + coll + " was created")
          if (ret.errmsg || (ret.note != "all indexes already exist" && ret.ok != 1)) {
            ret.coll = coll
            ret.keys = keys
            ret.options = options
            print(tojson(ret))      
          } else {
              //print( "Everything normal", JSON.stringify(ret)) 
          }
      }
      
      db.getCollectionInfos().forEach(function(coll) {
        //print( JSON.stringify( coll ))
        if (coll.type === "collection" ) {
          db[coll.name].getIndexes().forEach(function(index) {
              if ("_id_" !== index.name) {
                  //print( JSON.stringify( index ))
                  var indexKey = index.key        // save the key, and transform index into the "options"
                  delete index.key
                  delete index.ns     // namespace - not necessary
                  delete index.v      // not necessary
                  index.background = true     // optional: force background to be true
                  //native version: print("db." + coll.name + ".createIndex(" + JSON.stringify(indexKey) + ", " + JSON.stringify(index) + ")");
                  // this gives much more debug info
                  print("createIndex2(\"" + coll.name + "\", " + JSON.stringify(indexKey) + ", " + JSON.stringify(index) + ")");
                  }
          });
        }
      });
      

      如果使用“native”版本,结果是这样的,否则只会显示错误:

      db.dishes.createIndex({"submenu":1}, {"name":"submenu_1","ns":"dishly.disshes","background":true}) db.dishes.createIndex({"loc":"2dsphere"}, {"name":"loc_2dsphere","ns":"dishly.disshes","2dsphereIndexVersion":3,"background":true}) db.dishes.createIndex({"rs":-1}, {"name":"rs_-1","ns":"dishly.disshes","partialFilterExpression":{"rs":{"$gte":3}},"background":true}) db.dishes.createIndex({"loc":"2d","type":1,"status":1,"FSid":1,"rs":-1}, {"name":"loc_2d_type_1_status_1_rs_-1","ns":"dishly.disshes","background":true,"partialFilterExpression":{"rs":{"$gte":2}}}) db.dishes.createIndex({"_fts":"text","_ftsx":1,"loc.0":1,"loc.1":1,"rs":-1}, {"name":"d2_menu_submenu_text__loc__rs","ns":"dishly.disses","background":true,"weights":{"d2":1,"menu":1,"submenu":1}," default_language":"english","language_override":"language","textIndexVersion":3})

      【讨论】:

        【解决方案4】:

        试试这个脚本:

        var i, c, 
            co_name, co_new, 
            co_old, co_old_i, 
            _db = db.getSiblingDB('logs'), 
            _colls = ['activity.games', 'activity.session', 'activity.social', 'activity.store'];
        
        for (i in _colls){
            co_name = _colls[i];
            co_old = _db[co_name];
            co_old_i = co_old.getIndexes();
            if(co_old.count() > 0){
                co_old.renameCollection(co_name + '.old');
                _db.createCollection(co_name);  
                co_new = _db[co_name];
                for(c in co_old_i){
                    co_new.ensureIndex(co_old_i[c].key);
                }   
            }
        }
        

        https://gist.github.com/alejandrobernardis/8261327

        问候, 一个

        【讨论】:

          猜你喜欢
          • 2012-07-03
          • 2014-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-03
          • 2015-08-14
          • 1970-01-01
          相关资源
          最近更新 更多