Couchbase Lite機能解説：ドキュメントデータモデル

### 概要
Couchbase Liteは、組込・モバイルNoSQLドキュメント指向データベースです。Couchbase Lieteデータベースに格納されるドキュメントはJSONオブジェクトの形式を取ります。これは、キーと値のペアのコレクションであり、値は、数値、文字列、配列、さらにはネストされたオブジェクトなど、さまざまなタイプのデータになります。

ドキュメントは、ドキュメントIDによって識別されます。ドキュメントIDは、プログラムで指定するか、あるいは（UUIDとして）自動的に生成することができます。

ドキュメントIDは、データベース内で一意である必要があり、変更することができません。

### ドキュメントの作成・取得

新たにドキュメントを作成する際に、次のメソッド/イニシャライザーを使用できます。

- `MutableDocument(String id)`イニシャライザーは、特定のIDを使用して新しいドキュメントを作成するために使用することができます。
- 引数を取らない、`MutableDocument（）`イニシャライザーは、データベースによって文書IDをランダムに生成してドキュメントを作成するために使用することができます。

- また、`Database.getDocument（）`メソッドを、ドキュメントを取得するために使用することができます。データベースに存在しない場合は、nullを返します。このメソッドを使用して、指定されたIDのドキュメントがデータベースにすでに存在するかどうかを確認できます。

次のコード例は、ドキュメントを作成してデータベースに永続化します。

例1.新しいドキュメントを永続化する

```JAVA
MutableDocument newTask = new MutableDocument();
newTask.setString("type", "task");
newTask.setString("owner", "todo");
newTask.setDate("createdAt", new Date());
try {
    database.save(newTask);
} catch (CouchbaseLiteException e) {
    Log.e(TAG, e.toString());
}
```

### ドキュメントの変更

デフォルトでは、データベースからドキュメントが読み取られるとき、それは不変(immutable)です。
ドキュメントを更新するために（更新することができるインスタンスを作成するために）、`Document.toMutable（）`メソッドを使用します。

ドキュメントへの変更は、`save`メソッドが呼び出されたタイミングでデータベースに保持されます。

例2.ドキュメントを変更する

```JAVA
Document document = database.getDocument("xyz");
MutableDocument mutableDocument = document.toMutable();
mutableDocument.setString("name", "apples");
try {
    database.save(mutableDocument);
} catch (CouchbaseLiteException e) {
    Log.e(TAG, e.toString());
}
```

### 型付きアクセサ

#### スカラータイプ
`Document`クラスは、ブール、整数、浮動小数点、文字列など、さまざまなスカラー型のプロパティへのアクセサーを提供します。これらのアクセサーは、期待する型とJSONエンコーディングとの間の変換を処理します。

#### Dateアクセサー
Couchbase Liteでは、Dateアクセサーが提供されています。Dateは、プログラミング言語では一般的なデータ型ですが、JSONはネイティブにサポートしていないため、ISO-8601形式の文字列として日付データを格納するのが慣例です。

次の例では、`createdAt`プロパティに日付を設定し、`Document.getDate（）`アクセサーメソッドを使用してそれを読んでいます。

```JAVA
newTask.setValue("createdAt", new Date());
Date date = newTask.getDate("createdAt");
```

#### プロパティの確認
特定のプロパティがドキュメントに存在するかどうかを確認するには、`Document.Contains（String key）`メソッドを使用する必要があります。

プロパティが、文書内に存在しない場合にはそのゲッターメソッドのデフォルト値が返されます（`Document.getInt（）`の場合は`0`、`Document.getFloat（）`の場合は`0.0`、等）。

### バッチ操作

データベースに一度に複数の変更を加える場合は、それらをグループ化する方が高速です。次の例では、いくつかのドキュメントをバッチで永続化します。

```JAVA
try {
    database.inBatch(() -> {
        for (int i = 0; i < 10; i++) {
            MutableDocument doc = new MutableDocument();
            doc.setValue("type", "user");
            doc.setValue("name", "user " + i);
            doc.setBoolean("admin", false);
            try {
                database.save(doc);
            } catch (CouchbaseLiteException e) {
                Log.e(TAG, e.toString());
            }
            Log.i(TAG, String.format("saved user document %s", doc.getString("name")));
        }
    });
} catch (CouchbaseLiteException e) {
    Log.e(TAG, e.toString());
}
```


### ドキュメント変更イベントのリスニング

ドキュメントの変更を登録することもできます。次の例では、ID`user.john`を指定して、ドキュメントへの変更リスナーを登録しています。

```JAVA
database.addDocumentChangeListener(
    "user.john",
    change -> {
        Document doc = database.getDocument(change.getDocumentID());
        if (doc != null) {
            Toast.makeText(context, "Status: " + doc.getString("verified_account"), Toast.LENGTH_SHORT).show();
        }
    });
```

### ドキュメントの有効期限

ドキュメントに有効期限を設定できます。ドキュメントの有効期限が切れると、ドキュメントはデータベースから削除されます。

次の例では、ドキュメントのTTL（Time To Live）を現在の時刻から5分後に設定します。

```JAVA
// Purge the document one day from now
Instant ttl = Instant.now().plus(1, ChronoUnit.DAYS);
database.setDocumentExpiration("doc123", new Date(ttl.toEpochMilli()));

// Reset expiration
database.setDocumentExpiration("doc1", null);

// Query documents that will be expired in less than five minutes
Instant fiveMinutesFromNow = Instant.now().plus(5, ChronoUnit.MINUTES);
Query query = QueryBuilder
    .select(SelectResult.expression(Meta.id))
    .from(DataSource.database(database))
    .where(Meta.expiration.lessThan(Expression.doubleValue(fiveMinutesFromNow.toEpochMilli())));
```

### サーバーとの同期を行う場合の制約


`_id` 、`_ rev`、および `_sequence`は予約済みのキーワードであり、ドキュメントの最上位の属性として（基本的に）使用しないようにしてください。
このようなドキュメントをSync　Gatewayに同期しようとすると、エラーが発生します。

詳細なガイダンスについては、「[Sync Gateway-データモデリングガイドライン](https://docs.couchbase.com/sync-gateway/current/data-modeling.html)」を参照してください。

例3.予約済みキーのリスト

- _attachments

- _id

- _deleted

- _removed

- _rev

Couchbase Lite APIは、このような属性の使用を明示的に禁止（エラーと）していません。
これは、ドキュメントをサーバーと同期せずにローカルのみで使用する場合、またはピアツーピア同期でのみ使用する場合には、制約とならないためです。

## 参考情報

https://docs.couchbase.com/couchbase-lite/current/android/document.html