AWS S3に格納されたJSONデータの分析: Couchbaseの外部データソース機能紹介

# はじめに

この記事では、まずはじめに（第一部として）、Amazon Web Services（AWS）のSimple Storage Service（S3）にに保存されているデータを使った分析として、一般的と考えられるサービス・技術を取りあげ、それらが、どの様にJSONデータを取り扱っているかを説明します。

その後（第二部として）、NoSQLオブジェクト指向データベースであるCouchbase Serverを使った場合について、説明します。

# 第一部　代表的なサービス・技術による実現

## AWS S3データ分析
AWS　S3に保存されているデータを使ったデータ分析と言った場合、どんな選択肢が思い浮かぶでしょうか？ひとまず、以下の様な選択肢が代表的ではないかと思います。

- AWS Athena / Apache Presto
 - AthenaはAWSが提供するインタラクティブなクエリサービス。Amazon S3 内のデータを標準SQL を使用して分析できる。サーバーレスであり、実行したクエリに対して料金が発生。
- AWS EMR / Apache Hadoop (Hive)
 -  EMRはAWSが提供するビッグデータ（Hadoopエコシステム）プラットフォーム。EC2インスタンス、Amazon Elastic Kubernetes Service (EKS)、またはAWS Outposts上で利用可能。

ここでは、分析対象データが、CSVなどの、RDBのテーブルに準じた構造を持つデータではなく、JSONフォーマットであるケースについて、検討します。

## JSONデータの分析
Prestoであっても、Hiveであっても共通に、JSONとSQLクエリの橋渡しのために、以下の様なステップが行われます。

### Serialize/Deserializeを介したデータアクセス

SerDeライブラリを用いて、JSONファイルにアクセスします。

```sql
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
```
### STRUCT、ARRAY、MAP型を介したテーブル定義
`STRUCT`や`ARRAY`,`MAP`といった型定義を介してテーブル定義を行います（以下例）。

```sql
CREATE EXTERNAL TABLE twits (
	messages 
	ARRAY<
	    STRUCT<body: STRING,
	        symbols:ARRAY<STRUCT<symbol:STRING>>,
	        entities:STRUCT<sentiment:STRUCT<basic:STRING>>
	    >
	>
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
STORED AS TEXTFILE
LOCATION 's3://hoo/bar/'
```
この様にHiveやPrestoの様なSQLエンジンを用いて、S3に保存されているJSONデータを用いた分析を行うことが可能です。

# 第二部 Couchbase Serverによる実現

## Couchbase Serverにおけるデータ検索・分析

### QueryサービスとAnalyticsサービス
Couchbase Serverには、データに対してクエリを行うための２通りの方法が存在します。
一つは、アプリケーションからのデータ検索要求に応えるためのQueryサービス、そしてもう一つは、アドホックな分析や集計のためのAnalyticsサービスです。

## Analyticsサービス
 
###「外部データセット」サポート

Analyticsサービスには、「外部データセット」機能があります。
この拡張機能により、Analyticsサービスは、Amazon Web Services（AWS）Simple Storage Service（S3）に保存されたデータにアクセスし、Couchbaseデータと組み合わせて分析することができます。

#### サポートフォーマット
以下のファイル形式をサポートしています（.gzまたは.gzipの拡張子を持つ圧縮されたファイルについても、扱うことができます）。

- json
- csv （カンマ区切り）
- tsv （タブ区切り）

## CouchbaseをS3データ分析に用いる利点

### JSONデータの扱い

Couchbaseであれば、データセット定義時に、JSONの構造を意識したマッピングを行う必要はありません。データ構造は、JSONデータ自体から導き出される構造を、検索時に動的に用いることが可能です。

```sql
CREATE EXTERNAL DATASET reviews
ON BeerFestival
AT `beer-data`.myAwsLink
USING "json-data/reviews"
WITH {
  "format": "json",
  "include": ["*2018*.json", "*2019*.json"]
};
```

### 処理（集計）結果の保存

上記は、差別化ポイントとして十分説得力を持つ一方、S3上のデータを分析するという要件だけのために、Couchbaseを導入するのは、あまり現実的な提案とはいえないかもしれません。

一方、S3に格納されたデータへのアクセスは、応答速度において、データベースへのアクセスと比べて劣ります。
（単にクエリエンジンの部分だけを取り上げてAthenaと比べるのは適当ではないでしょうが）処理（集計）結果を、何らかのデータベースに保存する、という要件において、クエリエンジンとデータベースとの組み合わせとして、Couchbaseは、（AWSや他のソフトウェア・サービスの組み合わせとの比較において、メリット・デメリットを検討する意味のある）選択肢となると考えられます。


### メタデータの保存

また、Couchbaseの持つ、スキーマレスという特性を生かして、S3データのメタデータの管理のためにCouchbaseを使うことも考えられます（この場合は、同じカテゴリーのデータベースである、DynamoDBとの組み合わせにおいて、クエリエンジンとしての機能とデータベースとしての機能を総合的に比較することになるでしょう）。

# 利用手順解説

Couchbase ServerのAnalyticsサービスの「外部データソース」機能を使う手順の概要を紹介します。


## 利用データ

下記の二種類のデータを用います。

#### 製品データ
```JSON
{
"id":"Product_1",
"docType":"Product",
"productId":1,
"price":811.76,
"salePrice":70.14,
"productName":"Ergonomic Cotton Ball",
"desc":"Plastic fused metallic Ergonomic Cotton Ball",
}
```

#### レビューデータ
```JSON
{
"id":"Review_0001764a17a844279a2227e137cc4e36",
"docType":"Review",
"reviewId":"0001764a17a844279a2227e137cc4e36",
"productId":1,
"userId":5862,
"reviewerName":"M. Schaefer",
"reviewerEmail":"...@mmail.com",
"rating":5,
"title":"Works well and meets expectations.",
"review":"Product works great and will buy one more for my extended family.",
"reviewDate":1597273484
}

```
## S3リンク設定

S3リンクの設定は、REST APIおよびコマンドラインで行います。ここではREST APIでの実行例を示します。実行時に以下の様なパラメータを指定します。

- Analyticsサービスのホスト名
- Analyticsサービスのユーザー資格情報
- S3リンクにつける名前
- dataverse（Analyticsサービスにおける名前空間）
- リンクタイプ（S3）
- AWS S3アクセスに必要なアクセスキーID
- AWS S3アクセスに必要なシークレットアクセスキー
- AWS S3リージョン（例：us-west-2）

```shell

 curl -u <username>:<pwd> -X POST "http://<analytics_hostname>/analytics/link" -d dataverse=Default -d name=myS3Link -d type=S3 -d accessKeyId=... -d secretAccessKey=... -d region=us-west-2
```

## 外部データセット作成

データセットの作成は、以下の様なクエリを用いて行います。

```sql
 CREATE EXTERNAL DATASET S3productreviews ON cb-analytics-6.6-demo AT myS3Link USING “reviews” WITH { "format": "json", "include": "*.json" } ;
```

## データセットへのクエリ

データセットへのクエリ（とその結果）の例を示します。

```sql
SELECT p.productName, AVG(s.rating) AS ‘Rating’
FROM   S3productreviewss,productsp
WHERE  s.productId=p.productId
GROUP BY p.productName
ORDER BY AVG(s.rating) DESC
LIMIT  3;
```

### クエリ結果

```json
[
{"Rating":4.33,"productName":"Licensed Rubber Tuna"},
{"Rating":4.29,"productName":"Gorgeous Plastic Salad"},
{"Rating":3.86,"productName":"Intelligent Cotton Bike"}
]
```

## S3ファイルがJSON以外の場合

ここでは、データ自体に構造の情報を持たないCSVデータを扱うケースを紹介します。Presolや　Hiveとは異なり、Couchbaseにおいては、こちらが例外的なケースとなり、考慮しなければならない要素が介在します。

下記の様に、フォーマットを指定し、データ自体に含まれていない項目名の情報を定義します。

```sql
CREATE EXTERNAL DATASET S3productreviews
(
id STRING NOT UNKNOWN,
docType STRING NOT UNKNOWN,
reviewId STRING NOT UNKNOWN,
productId BIGINT,
userId BIGINT,
reviewerName STRING NOT UNKNOWN,
reviewerEmail STRING NOT UNKNOWN,
rating BIGINT,
title STRING NOT UNKNOWN,
review STRING NOT UNKNOWN,
reviewDate BIGINT
)
ON `cb-analytics-6.6-demo`
AT myS3link
USING "reviews"
WITH { "format":"csv", "include":"*.csv", "header":false };
```

# 参考情報

### Couchbase ブログ
[External Datasets: Accessing AWS S3 in Couchbase Analytics](https://blog.couchbase.com/external-datasets-extend-your-reach-with-couchbase-analytics/)

### AWS関連記事
[Amazon S3を中心とするデータ分析のベストプラクティス](https://www.db-tech-showcase.com/library/data-analytics-showcase/a12-hive-presto-spark-hbase)


[Amazon Athenaを使ってJSONファイルを検索してみる](https://dev.classmethod.jp/articles/athena-json/)

### Hive 実行例
[https://github.com/YoshiyukiKono/dsml_01_nlp/blob/master/hive_json_solution.ipynb](https://github.com/YoshiyukiKono/dsml_01_nlp/blob/master/hive_json_solution.ipynb)