Raspberry Piを使ったIoTアプリケーション開発に、NoSQLドキュメント指向組み込みデータベースCouchbase Liteを使ってみる

## はじめに

本稿では、Raspberry Piを活用したIoTアプリケーション開発に、NoSQLドキュメント指向モバイルデータベース Couchbase Liteを使うための具体的な方法について解説します。

本稿では、Couchbase Lite 3.0.0ベータ版をRaspberry Pi上で動かすC/C++アプリケーションで利用する際の手順を紹介します。

Couchbaseをモバイルアプリケーションで利用する意義については、以下の記事をご参考ください。

https://qiita.com/yoshiyuki_kono/items/3abd5e32801060a449d2

## 実行手順

### 動作確認環境

Raspberry Pi 3 Model b+を利用します。OSの情報について、以下確認結果を示します。

```shell
pi@raspberrypi:~ $ cat /etc/debian_version
9.4
pi@raspberrypi:~ $ cat /etc/issue
Raspbian GNU/Linux 9 \n \l
```

### インストール


#### APTメタパッケージダウンロード

UbuntuおよびDebianプラットフォームにCouchbase Liteをインストールする場合、Advanced Package Tool（apt）を使用するのが、最も簡単な方法です。

依存関係を含め、Couchbase　Liteを自動的に取得してインストールするためにaptが必要とするメタパッケージをダウンロードします。


```BASH
curl -O https://packages.couchbase.com/releases/couchbase-release/couchbase-release-1.0-noarch.deb
```

#### APTメタパッケージインストール

メタパッケージをインストールします。


```BASH
sudo apt install ./couchbase-release-1.0-noarch.deb
```



#### APTメタパッケージ編集

注：この手順は、ベータリリースでのみ必要です。

インストールにより作成された、URLのリストが含まれる`/etc/apt/sources.list.d/couchbase.list`を編集します。

以下は、`/etc/apt/sources.list.d/couchbase.list`ファイルの例です。Linuxディストリビューションによって、内容が若干異なる場合があります。

```BASH
deb [ arch=amd64 ] http://packages.couchbase.com/releases/couchbase-server/enterprise/deb/ focal focal/main
deb [ arch=amd64 ] http://packages.couchbase.com/releases/couchbase-server/community/deb/ focal focal/main
deb http://packages.couchbase.com/releases/couchbase-lite-repo/enterprise/deb/ focal focal/main
deb http://packages.couchbase.com/releases/couchbase-lite-repo/community/deb/ focal focal/main
# deb [ arch=amd64 ] http://beta-packages.couchbase.com/releases/couchbase-server/enterprise/deb/ focal focal/main
# deb [ arch=amd64 ] http://beta-packages.couchbase.com/releases/couchbase-server/community/deb/ focal focal/main

# deb http://beta-packages.couchbase.com/releases/couchbase-lite-repo/enterprise/deb/ focal focal/main
# deb http://beta-packages.couchbase.com/releases/couchbase-lite-repo/community/deb/ focal focal/main
```

コメントアウトされている最後の２行に、Couchbase Liteのベータパッケージに関する情報が含まれています。この行のコメントを解除します。



#### APTローカルデータベース更新

ローカルパッケージデータベースを更新します

```BASH
sudo apt update
```

#### APTインストール

必要なリリースパッケージをインストールします。ここでは開発用のパッケージをインストールします。


```BASH
sudo apt install libcblite-dev
```

上は、エンタープライズエディションを利用する例です。コミュニティエディションを使う場合は、下のパッケージ名を使います。

```BASH
sudo apt install libcblite-dev-community
```

### プログラミング・実行結果確認

下記の内容を持つファイル（ここでは`cbltest.c`とする）を作成します。

```c
#include "cbl/CouchbaseLite.h"

int main(void) {
    CBLError err;
    CBLDatabase* database = CBLDatabase_Open(FLSTR("mydb"), NULL, &err);

    if(!database) {
        // エラーハンドリング（簡潔のため、以降のエラー処理では記述を割愛）
        fprintf(stderr, "Error opening database (%d / %d)\n", err.domain, err.code);
        FLSliceResult msg = CBLError_Message(&err);
        fprintf(stderr, "%.*s\n", (int)msg.size, (const char *)msg.buf);
        FLSliceResult_Release(msg);
        return 1;
    }

    // ドキュメント作成
    CBLDocument* mutableDoc = CBLDocument_Create();
    FLMutableDict properties = CBLDocument_MutableProperties(mutableDoc);
    FLMutableDict_SetFloat(properties, FLSTR("version"), 3.0f);

    // ドキュメント保存
    CBLDatabase_SaveDocument(database, mutableDoc, &err);
    if(!CBLDatabase_SaveDocument(database, mutableDoc, &err)) {
        // 適宜、エラーハンドリングを実施
        return 1;
    }

    // ドキュメントIDを保存し、ドキュメントのメモリを解放
    // (注. FLSliceResultやFLStringResultとして確保した変数は明示的な解放が必要）
    FLStringResult id = FLSlice_Copy(CBLDocument_ID(mutableDoc));
    CBLDocument_Release(mutableDoc);

    // ドキュメント取得
    mutableDoc = CBLDatabase_GetMutableDocument(database, FLSliceResult_AsSlice(id), &err);
    if(!mutableDoc) {
        // 適宜、エラーハンドリングを実施
        // 注. エラーコード0は、ドキュメントが存在しないことを意味する
        return 1;
    }

    // ドキュメント更新・保存
    properties = CBLDocument_MutableProperties(mutableDoc);
    FLMutableDict_SetString(properties, FLSTR("language"), FLSTR("C"));
    if(!CBLDatabase_SaveDocument(database, mutableDoc, &err)) {
        // 適宜、エラーハンドリングを実施
        return 1;
    }

    // リードオンリーでドキュメントを取得（注. constを指定しています）
    const CBLDocument* docAgain = CBLDatabase_GetDocument(database, FLSliceResult_AsSlice(id), &err);
    if(!docAgain) {
        // 適宜、エラーハンドリングを実施
        // 注. エラーコード0は、ドキュメントが存在しないことを意味する
        return 1;
    }

    // ここでは、コピーを行なっていないため、後のメモリ解放は不要 (注.下記ではFLStringを利用し、FLStringResultでないことに留意)
    FLString retrievedID = CBLDocument_ID(docAgain);
    FLDict retrievedProperties = CBLDocument_Properties(docAgain);
    FLString retrievedLanguage = FLValue_AsString(FLDict_Get(retrievedProperties, FLSTR("language")));
    printf("Document ID :: %.*s\n", (int)retrievedID.size, (const char *)retrievedID.buf);
    printf("Learning %.*s\n", (int)retrievedLanguage.size, (const char *)retrievedLanguage.buf);

    CBLDocument_Release(mutableDoc);
    CBLDocument_Release(docAgain);
    FLSliceResult_Release(id);

    return 0;
}
```


`-lcblite`を指定して、例えば下記のようにコンパイルします。

```
$ gcc -g -o cbltest cbltest.c -lcblite
```

コンパイルの結果生成された`cbltest`を実行します。下記のような出力を確認することができます。

```
pi@raspberrypi:~ $ ./cbltest
Document ID :: ~UTapi2SRBTf5ZLW6Rfm1lX
Learning C
```

実行後、下記のようにCouchbase Liteデータベースファイルが作成されます。

```
drwx------  2 pi pi     4096 Dec  8 14:52 mydb.cblite2
```

## 最後に

本稿では、Raspberry Piを上での、C/C++アプリケーション開発に使うために、Couchbase Liteをインストールし、プログラムをコンパイルして、稼働確認を行うまでを扱いました。

最後に、さらなるステップに進むための情報を示して、本稿の締め括りとしたいと思います。

Couchbase Liteについての記事を以下の投稿で整理していますので、ご関心に応じて、参照してみてください。

https://qiita.com/yoshiyuki_kono/items/6a5bbad1b02196a25417

本稿の記事の内容（インストール、動作確認）に関する、一次情報として、下記のドキュメントがあります。Raspberry Pi以外のLinux環境、そしてLinux以外の環境でC/C++プログラミングにCouchbas Liteを使う方法も説明されています。

https://docs.couchbase.com/couchbase-lite/3.0/c/

Couchbase LiteのCサポートについて、下記のブログを参照することができます。


https://blog.couchbase.com/couchbase-lite-in-c/

https://blog.couchbase.com/beta-release-mobile-edge-computing/

本稿で扱っていませんが、Couchbase LiteをRaspberry Piで使う際のメリットとして、Couchbase Serverとの間での双方向のデータ同期が容易なことがあります。Couchbase Serverについては、日本語で読むことができるまとまった情報として、次の拙著を紹介させていただきます。

https://www.amazon.co.jp/-/en/%E6%B2%B3%E9%87%8E-%E6%B3%B0%E5%B9%B8/dp/429560030X/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=1636588872&sr=1-1