ApsaraDB for MongoDBを使ってデータをクラウドに保存する方法

このチュートリアルでは、**Alibaba Cloud**の**ApsaraDB for MongoDB**を使用して、データをクラウドに保存します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/invoice-application-backend-using-apsaradb-for-mongodb_582734)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

[ Alibaba Cloud Tech Share](https://www.alibabacloud.com/campaign/techshare?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw) 執筆者、 Sai Sarath Chandra。

[前回のチュートリアル](https://www.alibabacloud.com/blog/invoice-application-front-end-using-electronjs_582438?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)では、請求書アプリケーションのUIを作成しました。しかし、[最初の記事](https://www.alibabacloud.com/blog/what-is-electronjs-and-why-should-you-use-it_581971?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)で説明したように、デスクトップアプリケーションは貴重なデータを失うリスクに直面しています。

そこで、今回はAlibaba Cloudの[ApsaraDB for MongoDB](https://www.alibabacloud.com/product/apsaradb-for-mongodb?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)を使用して、データをクラウド上に保存します。クラウド上にデータを保存することで、Android、iOS、Webアプリケーションなどのアプリケーション間でデータを横断的に利用できるだけでなく、いつでもデータを取得することができます。アリババクラウドは、データをいつでもすぐに利用できるようにします。また、Alibaba Cloudが提供する[Automatic Elastic Scaling](https://www.alibabacloud.com/product/auto-scaling?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)を、いつでもビジネスに合わせて活用することができます。

###アプリケーションバックエンドの設定
ここでは、請求書発行アプリケーションのバックエンドについて説明します。

作成するAPIはNodeサーバとExpressJSフレームワークをベースにしています。

[https://github.com/saichandu415/Electron-Invoice-ApsaraDB-MongoDB](https://github.com/saichandu415/Electron-Invoice-ApsaraDB-MongoDB?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw) にあるコードをクローンして、Naviagateの "Invoice_Backend "フォルダに移動します。お好みのテキストエディタでファイルを開きます。

興味のあるファイルは2つだけです。

- Package.json
このファイルには、開発依存関係などの依存関係に関するすべての情報が格納されています。
- Server.js
ロジックを記述する重要なファイルです。本番環境では、Loopback のようなフレームワークを使用して、より多くの制御が可能な高性能な API を作成することをお勧めします。

Package.jsonでは、標準的な依存関係のセットを用意しています。

- Sprint-JS、mongoDB、node-UUID、formidable - データベースに接続し、実行時にURLを作成するためのものです。
- Expressとbody-parser - は、APIを作成し、受信したリクエストをJSON形式で取得するために使用されます。
Server.jsでは、次のようなコードがあります。

```
 http.createServer(app).listen(443, function () {
  console.log('Server for Invoice Backend running on port 443!');
});
```

上記は、443でリクエストを受け付けるhttpサーバを作成するための標準的な方法です。始める前に以下のインポートがあることを確認してください。

```
const bodyParser = require("body-parser");
const express = require("express");
const app = express();
var uuid = require('node-uuid');
var http = require('http');
var fs = require('fs');
var sprintf = require("sprintf-js").sprintf;
var mongoClient = require('mongodb').MongoClient;
```

これらのインポートはすべて、アプリケーションが正常に動作するために必要です。

`app.use(bodyParser.json());`

上記のこの行は、データベースを通過する前にjson形式で送信されるボディ情報をアンパースします。

ここでは、アプリケーションがconsole.log()行を通過するとすぐに情報を見ることができ、ここで何が起こっているかを理解することができるように、コンソールを使用しています。本番環境では、コンソールステートメントを使用することはお勧めできません。代わりに、同じことを達成するために適切なロギングフォーマットを持つことになります。

```
// ApsaraDB for MongoDB related configurations
var host1 = "dds-6gj540e0c157941.mongodb.ap-south-7.rds.aliyuncs.com";
var port1 = 3012;
var host2 = "dds-6gj54080c157942.mongodb.ap-south-7.rds.aliyuncs.com";
var port2 = 3012;
var username = "root";
var password = "Mongodb@12345";
var replSetName = "mgset-1050000641";
var demoDb = "admin";
```

MongoDB関連の情報は、ここを通ってデータベースに接続して操作を行う必要があります。

```
app.post('/data/invoice', (req, res) => {
  console.log(req.body);   
  var saveData = saveInvoiceData(req.body); 
  saveData.then(function(dbResponse){
    console.log(dbResponse);
    res.status(201).send(dbResponse);

  },function(err){
    console.log(err);
    res.status(400).send(err);
  });
});
```

これは、アプリケーションの送信ボタンをクリックしたときに発生する後処理です。内部的には、saveInvoiceDataを呼び出します。

saveInvoiceDataメソッドはDBに接続し、認証を行い、コレクションを見つけてDBにデータをプッシュします。



```
function saveInvoiceData(collectionData) {

  console.log(collectionData);
  return new Promise(function (resolve, reject) {
    // Logic to fetch from the MongoDB
    mongoClient.connect(url, function (err, db) {
      //if error console error
      console.log(err);
      if (err) {
        // Database not connected : error thrown
        console.error("connect err:", err);
        reject(err);
      } else {
        //Database connected successfully, get the DB Object
        var adminDb = db.admin();
        //Authenticate Database
        adminDb.authenticate(username, password, function (err, result) {
          if (err) {
            console.log("authenticate err:", JSON.stringyfy(err));
            reject(err);
          } else {
            console.log('Authenticated : ', JSON.stringify(result));
            // Get the Collection handle.
            var collection = db.collection("saleData");
            collection.insertOne(collectionData,function(err,result){
              if(err){
                reject(err);
              }else{
                resolve(result);
              }
            });
          }
        });
      }
    });
  });
}
```

メソッドはcollectionDataのjsonオブジェクトを受け取ります。そして、その他の情報はメソッドのコメントを見れば一目瞭然です。ここでは、データがコレクション "saleData "にプッシュされていることに注目してください。

ダッシュボードに関連するデータを取得するためのGETメソッドは以下の通りです。

```
app.get('/data/dashboard', (req, res) => {
  var getData = getDashboardData();
  getData.then(function(result){
    res.status(200).send(result);
  },function(err){
    console.log(err);
    res.status(400).send(err);
  });
});
```

GETメソッドは「getDashboardData()」を呼び出してデータを取得＆処理し、レスポンスを作成します。



```
function getDashboardData() {

  return new Promise(function (resolve, reject) {
    // Logic to fetch from the MongoDB
    mongoClient.connect(url, function (err, db) {
      //if error console error
      console.log(err);
      if (err) {
        // Database not connected : error thrown
        console.error("connect err:", err);
        reject(err);
      } else {
        //Database connected successfully, get the DB Object
        var adminDb = db.admin();
        //Authenticate Database
        adminDb.authenticate(username, password, function (err, result) {
          if (err) {
            console.log("authenticate err:", JSON.stringyfy(err));
            reject(err);
          } else {
            console.log('Authenticated : ', JSON.stringify(result));
            // Get the Collection handle.
            var collection = db.collection("saleData");
            collection.find({}).toArray(function (err, items) {
              if (err) {
                console.error('Unable to find data' + JSON.stringify(err));
              } else {
                console.info('data Fetched from MongoDB');
                var response = {}; 

                var datesArr = [];
                var salesArr = [];
                var ordersArr = [];

                var i =0;
                for(i=0; i<5; i++){
                  var totalSales = 0;
                var totalOrders = 0;
                  var d = new Date();
                  d.setDate(d.getDate() - i);
                  var month = d.getMonth() + 1;
                  var day = d.getDate();
                  var output = d.getFullYear() + '/' + (month < 10 ? '0' : '') + month + '/' + (day < 10 ? '0' : '') + day;
                  datesArr.push(output);
                console.log("In Loop 1 : "+i);
                  for(var k=0; k<items.length; k++){
                    var item = items[k];
                    if(item.invoiceDate == output){
                      totalSales = totalSales + item.totalAmount;
                      totalOrders = totalOrders+1;
                    }
                  }
                  salesArr.push(totalSales);
                  ordersArr.push(totalOrders);
                }
                response.datesArr = datesArr;
                response.salesArr = salesArr;
                response.ordersArr = ordersArr;
                resolve(response);
              }
            });
          }
        });
      }
    });
  });
}
```

ここにはたくさんのことが書かれています。以下のURIを叩くと、以下のようになります。

リクエスト : GET
[http:// VM IP : PORT>/data/dashboard](https://www.alibabacloud.com/blog/invoice-application-backend-using-apsaradb-for-mongodb_582734)

レスポンス ：

```
{
    "datesArr": [
        "2018/03/25",
        "2018/03/24",
        "2018/03/23",
        "2018/03/22",
        "2018/03/21"
    ],
    "salesArr": [
        0,
        4197.3,
        34,
        0,
        0
    ],
    "ordersArr": [
        0,
        1,
        1,
        0,
        0
    ]
}
```

getInvoiceData()では、データベースが接続されると、データの認証を行い、コレクションからデータをフェッチします。このメソッドでは、現在のデータから過去5日間の注文数と総販売額を確認するループを実行し、対応する配列にデータをプッシュします。

上記のレスポンスは/GETメソッドに送られるので、データ全体に対してforループを実行し、対応する配列にレスポンスを構築します。これはCPU集約的なタスクになるので、[Alibaba Cloud ECS](https://www.alibabacloud.com/product/ecs?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)インスタンスにデプロイしたミドルウェアに外部化しています。

これまでは、エンドポイントにアプリケーションを統合して、受信するデータが適切な形式になるようにする必要がありました。そのためのシンプルなクライアントであるpostmanを使ってみました。

###POSTMAN
以下は、POSTMANのスクリーンショットです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/c16cc6e5-f6c2-1e6a-1ce1-590d3fbaa51a.png)

- GET、POST、PUT、PATCH、DELETEのような異なるメソッドを呼び出すことができます。
- URI/アドレスバーがあり、クエリパラメータも受け付けることができます。
- 送信ボタンをクリックしてリクエストを行い、レスポンスを取得します。
- あなたはこれについての詳細を探ることができます、あなたはテストケースやピークパフォーマンステストを実行することができます。これはあなたが商業目的でそれを使用することができます。無料のツールです。

###APIのデプロイ
すでに[Alibaba Cloud ECS](https://www.alibabacloud.com/product/ecs?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)が設定されているはずです。よくわからない場合は、[ECSインスタンスの作成](https://www.alibabacloud.com/blog/3-ways-to-set-up-a-linux-server-on-alibaba-cloud_572384?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)に関する他のチュートリアルを参照してください。

**MongoDBインスタンスの作成：**
1、Alibaba Cloudコンソールで[ApsaraDB for MongoDB](https://www.alibabacloud.com/product/apsaradb-for-mongodb?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)を有効化する必要があります。
2、[ApsaraDB for MongoDB](https://www.alibabacloud.com/product/apsaradb-for-mongodb?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)コンソールに移動し、適切なゾーンを選択します。
3、Create Instanceをクリックします。
4、RAMや帯域幅などのインフラ関連の設定をすべて慎重に選択します。
5、パスワードを使用している場合は、将来の使用/参照のために慎重に保管してください。認証のためのコードに使用します。
6、プレビューを行い、利用規約に同意してインスタンスを作成します。
7、インスタンスが作成されたら、インスタンスの詳細に移動し、ECSインスタンスのIPをホワイトリストにします。
8、Whitelisting rulesに移動すると、Import ECS IPボタンが表示されます。ボタンをクリックすると、ECSイントラネットIPが自動的にインポートされます。
9、数秒で、コンソールに表示される「接続文字列」を見ることができるはずです。この情報を使って、GUIのMongoDBクライアントを[ApsaraDB for MongoDB](https://www.alibabacloud.com/product/apsaradb-for-mongodb?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)に接続することができます。
10、その他の個別情報は、コードを介してMongoDBを接続するために必要な情報です。この情報をコード内で置き換えてデータベースに接続するようにしてください。

###コードの実行
ECSインスタンスにコードをコピーした後、以下のコマンドを実行して正常に実行する必要があります。

**1.Npm インストール**
a.このパッケージは npm リポジトリから必要なすべてのパッケージをダウンロードしてインストールします。
**2.Npm start / node app.js**
a.これでアプリケーションが起動し、サーバーが起動したらAPIを呼び出せるようになるはずです。

**結論**
この記事では、Electron JSとは何かを見てきました。また、バックエンドAPIと一緒にユーザーインターフェースを作成しました。また、顧客のために作成している製品に付加価値を提供するデスクトップアプリケーションの[ApsaraDB for MongoDB](https://www.alibabacloud.com/product/apsaradb-for-mongodb?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)をどのように活用できるかを見ました。

全体のコードはgithubリポジトリで提供されています。何か質問がある場合は、以下のリンクから課題として提起してください。

[https://github.com/saichandu415/Electron-Invoice-ApsaraDB-MongoDB](https://github.com/saichandu415/Electron-Invoice-ApsaraDB-MongoDB?spm=a2c65.11461447.0.0.5e1d18a9ThuGKw)

コードを改善できると思われる方は、プルリクエストとして提出をお願いします。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*