Couchbase Lite機能解説：クエリ④ 結果セット


Couchbase LiteのSELECTステートメントに対して返された結果セットを処理する方法を解説します。

結果セットの形式とその処理は、使用する`SelectResult`ステートメントのタイプによって異なります。結果セット形式には、以下が含まれます。

- `SelectResult.all`：すべてのプロパティ

- `SelectResult.expression（property（ "name"））`：特定のプロパティ

- `SelectResult.expression（meta.id）`：ドキュメントIDのみ

- `SelectResult.expression（Function.count（Expression.all（）））.as（ "mycount"）`：データ（ドキュメント）件数のみ

クエリの結果を処理するには、最初に`Query.execute`を使用してクエリを実行します。

クエリを実行すると、通常、結果の配列、つまり結果セットが返されます。


ドキュメントのプロパティを返すクエリの結果セットは配列です。

配列の各行は、検索条件（WHEREステートメント）に一致したドキュメントのデータを表します。各行の構成はSelectResultとSELECTステートメント式の組み合わせによって決定されます。

ドキュメント件数をカウントするクエリの結果セットは、キーと値のペアとなり、クエリ中で設定した名前をキーとしてアクセスできます。

### すべてのプロパティを選択
#### クエリ
Selectクエリ条件に一致する各ドキュメントのすべてのドキュメントプロパティを返すこのタイプのクエリのステートメントは、かなり単純です。


```JAVA
        try {
          this_Db = new Database("hotels");
        } catch (CouchbaseLiteException e) {
          e.printStackTrace();
        }

      Query listQuery = QueryBuilder.select(SelectResult.all())
              .from(DataSource.database(this_Db));
```

#### 結果セットの形式
`SelectResult.all`を使用したクエリによって返される結果セットは、クエリ条件に一致するドキュメントごとに1つずつ、ディクショナリオブジェクトの配列です。

結果オブジェクトごとに、キーはデータベース名であり、「値」は各ドキュメントプロパティをキーと値のペアとして表すディクショナリです。

```JSON
[
  {
    "travel-sample": { 
      "callsign": "MILE-AIR",
      "country": "United States",
      "iata": "Q5",
      "icao": "MLA",
      "id": 10,
      "name": "40-Mile Air",
      "type": "airline"
    }
  },
  {
    "travel-sample": { 
      "callsign": "ALASKAN-AIR",
      "country": "United States",
      "iata": "AA",
      "icao": "AAA",
      "id": 10,
      "name": "Alaskan Airways",
      "type": "airline"
    }
  }
]
```

#### 結果セットへのアクセス
次に示すように、各行の値を辞書に変換して、取得したドキュメントのプロパティにアクセスします。

例15.ドキュメントプロパティの使用（すべて）

```JAVA
        try {
            for (Result result : listQuery.execute().allResults()) {
                // get the k-v pairs from the 'hotel' key's value into a dictionary
                thisDocsProps = result.getDictionary(0)); 
                thisDocsId = thisDocsProps.getString("id");
                thisDocsName = thisDocsProps.getString("Name");
                thisDocsType = thisDocsProps.getString("Type");
                thisDocsCity = thisDocsProps.getString("City");

                // Alternatively, access results value dictionary directly
                final Hotel hotel = new Hotel();
                hotel.Id = result.getDictionary(0).getString("id"); 
                hotel.Type = result.getDictionary(0).getString("Type");
                hotel.Name = result.getDictionary(0).getString("Name");
                hotel.City = result.getDictionary(0).getString("City");
                hotel.Country= result.getDictionary(0).getString("Country");
                hotel.Description = result.getDictionary(0).getString("Description");
                hotels.put(hotel.Id, hotel);

            }
        } catch (CouchbaseLiteException e) {
            e.printStackTrace();
        }
```


### 特定のプロパティを選択
#### クエリ
ここでは、クエリが返すドキュメントプロパティを指定するために`SelectResult.expression(property("<property-name>")))`使用します。


```JAVA
        try {
          this_Db = new Database("hotels");
        } catch (CouchbaseLiteException e) {
          e.printStackTrace();
        }

        Query listQuery =
                QueryBuilder.select(SelectResult.expression(Meta.id),
                        SelectResult.property("name"),
                        SelectResult.property("Name"),
                        SelectResult.property("Type"),
                        SelectResult.property("City"))
                        .from(DataSource.database(this_Db));
```

#### 結果セットの形式
特定のドキュメントプロパティのみを選択したときに返される結果セットは、クエリ条件に一致するドキュメントごとに1つずつ、ディクショナリオブジェクトの配列です。

各結果オブジェクトは、選択した各ドキュメントプロパティのキーと値のペアで構成されます。


```JSON
[
  { 
    "id": "hotel123",
    "type": "hotel",
    "name": "Hotel Ghia"
  },
  { 
    "id": "hotel456",
    "type": "hotel",
    "name": "Hotel Deluxe",
  }
]
```


#### 結果セットへのアクセス
各行を辞書に変換して、取得したプロパティにアクセスします。


```JAVA
        try {
            for (Result result : listQuery.execute().allResults()) {

                // get data direct from result k-v pairs
                final Hotel hotel = new Hotel();
                hotel.Id = result.getString("id");
                hotel.Type = result.getString("Type");
                hotel.Name = result.getString("Name");
                hotel.City = result.getString("City");

                // Store created hotel object in a hashmap of hotels
                hotels.put(hotel.Id, hotel);

                // Get result k-v pairs into a 'dictionary' object
                Map <String, Object> thisDocsProps = result.toMap();
                thisDocsId =
                        thisDocsProps.getOrDefault("id",null).toString();
                thisDocsName =
                        thisDocsProps.getOrDefault("Name",null).toString();
                thisDocsType =
                        thisDocsProps.getOrDefault("Type",null).toString();
                thisDocsCity =
                        thisDocsProps.getOrDefault("City",null).toString();

            }
        } catch (CouchbaseLiteException e) {
            e.printStackTrace();
        }
```

### ドキュメントIDのみを選択
#### クエリ
ドキュメントのプロパティを直接取得すると、メモリや処理時間が過剰に消費される場合は、通常、このタイプのクエリを使用します。


```JAVA
      try {
        this_Db = new Database("hotels");
      } catch (CouchbaseLiteException e) {
        e.printStackTrace();
      }

      Query listQuery =
              QueryBuilder.select(SelectResult.expression(Meta.id).as("metaID"))
                      .from(DataSource.database(this_Db));
```

#### 結果セットの形式
`SelectResult.expression(meta.id)`というSelectResult式を使用したクエリによって返される結果セットは、クエリ条件に一致するドキュメントごとに1つずつ、ディクショナリオブジェクトの配列です。各結果オブジェクトは`id`プロパティの値として、どドキュメントIDを持ちます。


```JSON
[
  {
    "id": "hotel123"
  },
  {
    "id": "hotel456"
  },
]
```

#### 結果セットへのアクセス
この場合、idを使用してデータベースからドキュメントを取得することにより、必要なドキュメントのプロパティにアクセスします。


```JAVA
        try {
            for (Result result : listQuery.execute().allResults()) {

                // get the ID form the result's k-v pair array
                thisDocsId = result.getString("metaID"); 

                // Get document from DB using retrieved ID
                Document thisDoc = this_Db.getDocument(thisDocsId);

                // Process document as required
                thisDocsName = thisDoc.getString("Name");

            }
        } catch (CouchbaseLiteException e) {
            e.printStackTrace();
        }
```


### カウントのみを選択

#### クエリ

以下は、カウントのみを選択するクエリの例です。

```JAVA
      Query listQuery = QueryBuilder.select(
              SelectResult.expression(Function.count(Expression.string("*"))).as("mycount")) 
              .from(DataSource.database(this_Db));
```

エイリアス名、`mycount`は、結果セットのカウント値にアクセスするために使用されます。

#### 結果セットの形式

`Select.expression(Function.count(Expression.all)))`によって返される結果セットは、キーと値のペアです。キーは、`SelectResult.as`を使用して定義された名前です。


```JSON
{
  "mycount": 6
}
```

#### 結果セットへのアクセス
エイリアス名を使用してカウントにアクセスします（この例では`mycount`）。

```JAVA
        try {
            for (Result result : listQuery.execute()) {

                // Retrieve count using key 'mycount'
                Integer altDocId = result.getInt("mycount");

                // Alternatively, use the index
                Integer orDocId = result.getInt(0);
            }
            // Or even miss out the for-loop altogether
            Integer resultCount = listQuery.execute().next().getInt("mycount");

        } catch (CouchbaseLiteException e) {
            e.printStackTrace();
        }

```

#### ページネーションの処理
大量の結果を返すクエリでページネーションを処理する1つの方法は、結果をバッチで取得することです。`limitandoffset`機能を使用して、指定されたオフセットから始まる定義された数の結果を返します。

例25.クエリのページ化


```JAVA
        try {
          this_Db = new Database("hotels");
        } catch (CouchbaseLiteException e) {
          e.printStackTrace();
        }

        int thisOffset = 0;
        int thisLimit = 20;

        Query listQuery =
                QueryBuilder
                        .select(SelectResult.all())
                        .from(DataSource.database(this_Db))
                        .limit(Expression.intValue(thisLimit),
                                  Expression.intValue(thisOffset)); 
```



## 参考情報

https://blog.couchbase.com/sql-for-json-query-interface-couchbase-mobile/