【问题标题】:MongoDB How to copy index definitions from one collection to another?MongoDB 如何将索引定义从一个集合复制到另一个集合?
【发布时间】:2017-03-31 21:52:54
【问题描述】:

我知道有一种方法可以执行 db.collection.getIndexes() ,它将列出为集合定义的所有索引。有没有办法将这些索引定义复制并创建到另一个集合?

有很多,我不想一个一个做。

关于重复的问题评论:我不想复制一个集合。我希望以可以应用于另一个集合的格式导出索引。

【问题讨论】:

标签: mongodb


【解决方案1】:

例如,我有一个现有的 user 集合,其中包含索引 _id_、name_1、email_1 和 网站_1

然后我有另一个名为 usertest 的集合,我想将索引从 user 集合复制到 usertest 集合。以下命令适用于这种情况:

  1. 复制索引键和索引选项

    var indexes = db.user.getIndexes();
    
    indexes.forEach(function(index){
        delete index.v;
        delete index.ns;
        var key = index.key;
        delete index.key
        var options = [];
        for (var option in index) {
            options.push(index[option]);
        }
       db.usertest.createIndex(key, options);
    });
    
  2. 仅复制索引键(批处理)

    var indexKeys = db.user.getIndexKeys();
    db.usertest.createIndexes(indexKeys);
    

希望这会有所帮助。这是文档:createIndexes

【讨论】:

  • 我看到了 db.collection.getIndexKeys() 方法。我立即看到的问题是它没有列出索引的选项,对吗?所以用户集合上的唯一索引在 usertest 集合上不会是唯一的:/
  • 您知道要传递给 getIndexKeys() 方法以便返回索引选项的任何参数吗?我在文档上找不到方法。
  • 据我所知没有这样的参数。我已经更新了我的代码以复制索引选项。希望对你有帮助。
  • options.push(index['option']); 中的'option' 应该没有引号,对吧?我们想要变量,而不是字符串“选项”?而且,这可能会抛出"Index options that are supplied in array form may only specify three values: name, unique, dropDups",因此最好将options 作为对象发送,所以第7 行:var options = {},然后第10 行:options[option] = index[option]
【解决方案2】:

要直接在 MongoDB 中执行此操作,请执行以下操作,

以下命令将为所有集合的现有索引生成 mongo DB 查询,

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);
    });
});

上面的命令会根据你的收集量输出如下内容

db.User.createIndex({"createdAt":-1}, {"background":true}); 

db.User.createIndex({"updatedAt":-1}, {"background":true}); 

db.Login.createIndex({"loginDate":-1}, {"background":true}); 

因此,执行此操作后,复制上面生成的 MongoDB 查询以创建新集合的索引,更改其中的集合名称然后执行它。

例如:要将属于 User 集合的所有索引复制到 UserNew 集合,我将查询的旧集合名称重命名为 new 如下所示并执行它,就是这样,现在您已将所有索引复制到一个旧系列的新系列。

db.UserNew.createIndex({"createdAt":-1}, {"background":true}); 

db.UserNew.createIndex({"updatedAt":-1}, {"background":true}); 

致谢:http://aleksandrmaiorov.com/2019/04/29/mongo-how-to-copy-indexes-from-one-database-to-another/

【讨论】:

    【解决方案3】:

    感谢 Rocky 和 ​​Bloke 的回答,这对我帮助很大 这是 Bloke 建议的综合版本。 并在生产中。我们想确保背景:真实 用于在复制索引创建时避免从站暂停查询。

    var indexes = db.user.getIndexes();
    // we skipped the __id__ indexes and set the default background: true option
    indexes.forEach(function(index){
        if(index.name =='_id_'){
         print("we are skip the _id_ index")
        }else{
        delete index.v;
        delete index.ns;
        var key = index.key;
        delete index.key
        var options = {};
        for (var option in index) {
            options[option] = index[option]
        }
        options['background'] = true;
        printjson(key);
        printjson(options);
        db.usertest.createIndex(key, options);
    
       }
    });
    

    【讨论】:

      【解决方案4】:

      Rocky Li 的回答很有帮助,但在撰写本文时没有正确创建索引选项(它收集了选项值但没有收集键)。以下修改对我有用:

      var indexes = db.user.getIndexes();
      
      indexes.forEach(function(index){
          delete index.v;
          delete index.ns;
          var key = index.key;
          delete index.key
      
          // uncomment if you want to ensure creation is in background
          //if(!('background' in index))
              //index['background'] = true;
      
         db.user.createIndex(key, index);
      });
      

      【讨论】:

        【解决方案5】:

        从一个数据库复制所有索引到另一个数据库

         use firstDbName;
         var indexKeyArray = [];
         db.getCollectionNames().forEach(function(collection) {
         var indexKeys = db[collection].getIndexKeys();
         var base = {};
         base["name"] = collection;
         base["indices"] = indexKeys
         indexKeyArray.push(base);
        });
        #printjson(indexKeyArray);
        use destinationDbName;
        indexKeyArray.forEach(function(data) {
          db[data.name].createIndexes(data.indices);
        });
        

        【讨论】:

          猜你喜欢
          • 2023-03-13
          • 1970-01-01
          • 1970-01-01
          • 2020-12-25
          • 1970-01-01
          • 2021-09-07
          • 2021-06-14
          • 2023-01-10
          • 2015-01-18
          相关资源
          最近更新 更多