先日、Cloudant のデータベースのバックアップ(というかダンプというか、スナップショットというか、、)を撮る方法をこちらで紹介しました:
Cloudant のデータベースダンプとリストア

この中では /_all_docs?include_docs=true に GET アクセスすることで指定データベース内の全ドキュメントを中身ごと取り出す方法でダンプを取得する方法を紹介しました。

併せて、取得したダンプファイルを /_bulk_docs に POST してリストアする、という方法も紹介しました。この方法で確かにデータそのものは指定データベースに入るのですが、JSON の構造が少し変わってしまいます。「リストア」という観点では不十分でした。

というわけで、今回は JSON の構造を変えずにリストアする方法を紹介します。といってもコマンドでどうにかするのではなく、取得したダンプファイルを読み込んで、少しフォーマットを変更した上で同じ /_bulk_docs コマンドでリストアする、という方法です。フォーマットを変更する箇所はプログラミングでツール化しました(赤字はコメント):
public class DbRestore {
  static String c_baseurl = "https://username.cloudant.com"; //. Cloudant サーバー
  static String c_username = "username"; //. ユーザー名
  static String c_password = "password"; //. パスワード
  static String c_db = "newdb"; //. リストア先データベース名(作成しておく必要があります)
  static String c_dumpfile = "olddb.dump"; //. 読み込むダンプファイル名

  public static void main(String[] args) {
    try{
      //. ダンプファイルを読み込む
      String lines = "";
      BufferedReader br = new BufferedReader( new FileReader( new File( c_dumpfile ) ) );
      String line = br.readLine();
      while( line != null ){
        lines += ( line + "\n" );
        line = br.readLine();
      }
      br.close();

      //. ダンプファイル内のドキュメントデータを1つずつ読み込み、リストア用にフォーマットを変更
      String docs2 = "{\"docs\":[\n";
      JSONParser parser = new JSONParser();
      JSONObject obj = ( JSONObject )parser.parse( lines );
      JSONArray docs = ( JSONArray )obj.get( "docs" );
      for( int i = 0; i < docs.size(); i ++ ){
        JSONObject doc0 = ( JSONObject )docs.get( i );
        JSONObject doc = ( JSONObject )doc0.get( "doc" );
        JSONObject d = ( JSONObject )doc.get( "d" );
        if( i > 0 ){ docs2 += ","; }
        docs2 += "{\"d\":" + d.toJSONString() + "}\n";
      }
      docs2 += "]}";

      //. リストア用に変更したダンプデータを /_bulk_docs にポスト
      String url = c_baseurl + "/" + c_db + "/_bulk_docs";
      HttpClient client = new HttpClient();
      byte[] b64data = Base64.encodeBase64( ( c_username + ":" + c_password ).getBytes() );
      PostMethod post = new PostMethod( url );
      post.setRequestHeader( "Authorization", "Basic " + new String( b64data ) );
      post.setRequestHeader( "Content-Type", "application/json" );
      post.setRequestBody( docs2 );
      int sc = client.executeMethod( post );
      String result = post.getResponseBodyAsString();

      //. 結果確認
      System.out.println( "Status = " + sc );
      System.out.println( "Result = " + result );
    }catch( Exception e ){
      e.printStackTrace();
    }
  }
}


このコードは JSON-SimpleApache HTTP Client ライブラリを使って /_bulk_docs にダンプデータをポストする処理を Java で実装しています。ダンプデータをそのままポストすると情報は再現できるのですが、データフォーマットが変わってしまいます。その問題を回避すべく、ポスト前に必要なフォーマット変換を行っていて、ダンプ前のデータフォーマットが変わらないように(_id 値や _rev 値は変わります)ポストしています。

このコードの c_dumpfile に前回の方法でダンプしたファイル名を指定し、Java で動かせばダンプファイルの中身をリストアできるはずです。