JavaScript >> Javascript 文檔 >  >> Node.js

使用 Node 和 Monk 進行 MongoDB 遷移

最近,我們的一位頂級用戶抱怨他們的 Storify 帳戶無法訪問。我們檢查了生產數據庫,似乎該帳戶可能已被使用用戶帳戶憑據的人破壞並惡意刪除。多虧了 MongoHQ 的出色服務,我們在不到 15 分鐘的時間內就完成了備份數據庫。
有兩個選項可以繼續遷移:

  1. Mongo shell 腳本
  2. Node.js 程序

因為 Storify 用戶帳戶刪除涉及刪除所有相關對象——身份、關係(關注者、訂閱)、喜歡、故事——我們決定繼續使用後一種選擇。它運行良好,這是一個簡化版本,您可以將其用作 MongoDB 遷移的樣板(也在 gist.github.com/4516139)。

恢復 MongoDB 記錄

讓我們加載我們需要的所有模塊:Monk、Progress、Async 和 MongoDB:

var async = require('async');
var ProgressBar = require('progress');
var monk = require('monk');
var ObjectId=require('mongodb').ObjectID;

順便說一句,Monk 由 LeanBoost 製作,是一個微小的層,它為 Node.JS 中的 MongoDB 使用提供了簡單而實質性的可用性改進。

Monk 採用以下格式的連接字符串:

username:password@dbhost:port/database

所以我們可以創建以下對象:

var dest = monk('localhost:27017/storify_localhost');
var backup = monk('localhost:27017/storify_backup');

我們需要知道我們要恢復的對象 ID:

var userId = ObjectId(YOUR-OBJECT-ID); 

這是一個方便的恢復 我們可以通過指定查詢重用該函數以從相關集合中恢復對象(有關 MongoDB 查詢的更多信息,請轉到發布 Querying 20M-Record MongoDB Collection。要調用它,只需將集合的名稱作為字符串傳遞,例如 "stories" 以及將此集合中的對象與您的主要對象相關聯的查詢,例如 {userId:user.id} .需要進度條來在終端中向我們展示漂亮的視覺效果。

var restore = function(collection, query, callback){
  console.info('restoring from ' + collection);
  var q = query;
  backup.get(collection).count(q, function(e, n) {
    console.log('found '+n+' '+collection);
    if (e) console.error(e);
    var bar = new ProgressBar('[:bar] :current/:total :percent :etas', { total: n-1, width: 40 })
    var tick = function(e) {
      if (e) {
        console.error(e);
        bar.tick();
      }
      else {
        bar.tick();
      }
      if (bar.complete) {
        console.log();
        console.log('restoring '+collection+' is completed');
        callback();                
      }
    };
    if (n>0){
      console.log('adding '+ n+ ' '+collection);
      backup.get(collection).find(q, { stream: true }).each(function(element) {
        dest.get(collection).insert(element, tick);
      });        
    } else {
      callback();
    }
  });
}

現在我們可以使用 async 來調用 restore 上面提到的功能:

async.series({
  restoreUser: function(callback){   // import user element
    backup.get('users').find({_id:userId}, { stream: true, limit: 1 }).each(function(user) {
      dest.get('users').insert(user, function(e){
        if (e) {
          console.log(e);
        }
        else {
          console.log('resored user: '+ user.username);
        }
        callback();
      });
    });
  },

  restoreIdentity: function(callback){  
    restore('identities',{
      userid:userId
    }, callback);
  },

  restoreStories: function(callback){
    restore('stories', {authorid:userId}, callback);
  }

  }, function(e) {
  console.log();
  console.log('restoring is completed!');
  process.exit(1);
});

完整代碼可在 gist.github.com/4516139 和此處獲得:

var async = require('async');
var ProgressBar = require('progress');
var monk = require('monk');
var ms = require('ms');
var ObjectId=require('mongodb').ObjectID;

var dest = monk('localhost:27017/storify_localhost');
var backup = monk('localhost:27017/storify_backup');

var userId = ObjectId(YOUR-OBJECT-ID); // monk should have auto casting but we need it for queries

var restore = function(collection, query, callback){
  console.info('restoring from ' + collection);
  var q = query;
  backup.get(collection).count(q, function(e, n) {
    console.log('found '+n+' '+collection);
    if (e) console.error(e);
    var bar = new ProgressBar('[:bar] :current/:total :percent :etas', { total: n-1, width: 40 })
    var tick = function(e) {
      if (e) {
        console.error(e);
        bar.tick();
      }
      else {
        bar.tick();
      }
      if (bar.complete) {
        console.log();
        console.log('restoring '+collection+' is completed');
        callback();                
      }
    };
    if (n>0){
      console.log('adding '+ n+ ' '+collection);
      backup.get(collection).find(q, { stream: true }).each(function(element) {
        dest.get(collection).insert(element, tick);
      });        
    } else {
      callback();
    }
  });
}

async.series({
  restoreUser: function(callback){   // import user element
    backup.get('users').find({_id:userId}, { stream: true, limit: 1 }).each(function(user) {
      dest.get('users').insert(user, function(e){
        if (e) {
          console.log(e);
        }
        else {
          console.log('resored user: '+ user.username);
        }
        callback();
      });
    });
  },

  restoreIdentity: function(callback){  
    restore('identities',{
      userid:userId
    }, callback);
  },

  restoreStories: function(callback){
    restore('stories', {authorid:userId}, callback);
  }

  }, function(e) {
  console.log();
  console.log('restoring is completed!');
  process.exit(1);
});
           

要啟動它,請運行 npm install/update 並更改硬編碼的數據庫值。


Tutorial JavaScript 教程
  1. 新前沿展示頁面

  2. React 面向鉤子的 Redux 編碼模式,沒有 thunk 和動作創建者

  3. StackEdit 4.0:多實例和本地託管

  4. Nodejs 更新戰爭(模塊 n ?!)

  5. 減少 CSS 樣式

  6. 你的替代解決方案是什麼?挑戰#50

  7. Package.json 值可在 npm/yarn 腳本中訪問

  1. 啤酒節🏆 來了

  2. 使用 Express-Kun 創建簡單的 Express JWT 身份驗證中間件(無需設置 Passport!)

  3. Javascript 和 Node.js 的超簡單執行跟踪

  4. Mongoose for MongoDB 簡介

  5. 如何在 React 中構建動畫微交互

  6. 從 jquery 訪問 json 數據

  7. 使用 jQuery 從 URL 獲取 ID

  1. React Native:滾動視圖和平面列表

  2. 如何使用 CodeMirror 顯示其他客戶端光標(插入符號)位置

  3. 在瀏覽器中使用 VR/AR 處理視頻

  4. 洗牌並顯示選定的主題