JSON ドライバー: 階層データの解析



最近のサービスでは、データを JSON オブジェクト、配列、またはそれらの組み合わせとして返却・保存することが一般的です。これは階層データの保存には便利ですが、一般的な BI、レポーティング、ETL ツールで扱うには少し工夫が必要です。ネストした JSON データを扱うには、主に以下の2つの手法があります。

  • 水平・垂直フラット化を使用して、ネストした配列やオブジェクトにドリルダウンする方法
  • データ構造を解析し、既存の階層に基づいてリレーショナルモデルを構築する方法

この記事では、これら2つの手法の違いと、ドライバーでどちらの手法を使用するかを設定する方法について説明します。別のナレッジベース記事では、水平・垂直フラット化を使用した JSON データの解釈方法についてより詳しく解説しています。

Document、Flattened Documents、Relational モデリング



CData JSON ドライバーは、完全なドキュメントのレポート、暗黙的に JOIN されたフラット化ドキュメント、またはリレーショナルモデルの構築によって NoSQL データを管理します。完全なドキュメントをレポートする場合、ドライバーはネストしたオブジェクト配列を集約された JSON オブジェクトとして返します。フラット化ドキュメントを扱う場合、ドライバーはネストした配列オブジェクトを単一のテーブルとして解釈し、SELECT クエリを実行することで暗黙的に JOIN を実行できます。リレーショナルモデルを構築する場合、ドライバーは検出されたオブジェクトと構造に基づいて結果を個別のテーブルとして解釈し、NoSQL データのリレーショナルモデルを表示して、明示的な SQL JOIN クエリを実行できます。以下に各手法の例を示します。

  • Document: NoSQL データのトップレベルのドキュメントビュー。集約された配列を含みます。
  • Flattened Documents: ネストした配列オブジェクトが親オブジェクトに暗黙的に JOIN されます。
  • Relational Modeling: すべての NoSQL データを個別のテーブルとして表示します。

参考として、これらの例は以下のサンプル JSON ドキュメントに基づいています。

サンプルドキュメント



このサンプルドキュメントには、人物、所有する車両、およびそれらの車両に対して行われたさまざまなメンテナンスサービスのエントリが含まれています。

people.json

{
  "people": [
    {
      "personal": {
        "age": 20,
        "gender": "M",
        "name": {
          "first": "John",
          "last": "Doe"
        }
      },
      "vehicles": [
        {
          "type": "car",
          "model": "Honda Civic",
          "insurance": {
            "company": "ABC Insurance",
            "policy_num": "12345"
          },
          "maintenance": [
            {
              "date": "07-17-2017",
              "desc": "oil change"
            },
            {
              "date": "01-03-2018",
              "desc": "new tires"
            }
          ]
        },
        {
          "type": "truck",
          "model": "Dodge Ram",
          "insurance": {
            "company": "ABC Insurance",
            "policy_num": "12345"
          },
          "maintenance": [
            {
              "date": "08-27-2017",
              "desc": "new tires"
            },
            {
              "date": "01-08-2018",
              "desc": "oil change"
            }
          ]
        }
      ],
      "source": "internet"
    },
    {
      "personal": {
        "age": 24,
        "gender": "F",
        "name": {
          "first": "Jane",
          "last": "Roberts"
        }
      },
      "vehicles": [
        {
          "type": "car",
          "model": "Toyota Camry",
          "insurance": {
            "company": "Car Insurance",
            "policy_num": "98765"
          },
          "maintenance": [
            {
              "date": "05-11-2017",
              "desc": "tires rotated"
            },
            {
              "date": "11-03-2017",
              "desc": "oil change"
            }
          ]
        },
        {
          "type": "car",
          "model": "Honda Accord",
          "insurance": {
            "company": "Car Insurance",
            "policy_num": "98765"
          },
          "maintenance": [
            {
              "date": "10-07-2017",
              "desc": "new air filter"
            },
            {
              "date": "01-13-2018",
              "desc": "new brakes"
            }
          ]
        }
      ],
      "source": "phone"
    }
  ]
}

Document モデリング



NoSQL データのトップレベルのドキュメントビューを使用すると、階層的な配列を処理・解析するための時間とリソースを節約しながら、トップレベルのフィールドとオブジェクトに簡単にアクセスできます。CData ドライバーは、最上位の繰り返し要素に基づいて JSON ストアを表示し、すべてのネストした配列を単一のカラムとして扱うように設定できます。このモードでは、ドライバーはストリーミングを使用して JSON データを読み取り、クエリごとに返されたデータを1回だけ解析します。

以下は、上記のサンプルドキュメントに基づいたサンプルクエリとその結果です。このクエリは、JSON パス "$.people" に基づいて単一の "people" テーブルを生成します。

接続文字列

Data Model 接続プロパティを "Document" に設定し、JSON Path 接続プロパティを "$.people" に設定すると、上記のクエリを実行してサンプル結果セットを確認できます。

DataModel=Document;JSONPath='$.people';

メタデータ

以下のテーブルは、Document データモデルを使用した場合のメタデータを示しています。

People
カラム データ型
personal.age Integer
personal.gender String
personal.name.first String
personal.name.last String
source String
vehicles String

クエリ

このクエリでは、トップレベルのオブジェクト要素と配列を結果に取り込みます。トップレベルのオブジェクト要素は、デフォルトのオブジェクトフラット化により利用可能です。配列は集約された JSON として返されます。

SELECT
  [personal.age] AS age,
  [personal.gender] AS gender,
  [personal.name.first] AS name_first,
  [personal.name.last] AS name_last,
  [source],
  [vehicles]
FROM
  [people]

結果

データのドキュメントビューでは、"personal" オブジェクトが4つのカラムにフラット化され、"source" と "vehicles" 要素がそれぞれ個別のカラムとして返され、結果として6つのカラムを持つテーブルになります。

age gender name_first name_last source vehicles
20 M John Doe internet [{"type":"car","model":"Honda Civic","insurance":{"company":"ABC Insurance","policy_num":"12345"},"maintenance":[{"date":"07-17-2017","desc":"oil change"},{"date":"01-03-2018","desc":"new tires"}]},{"type":"truck","model":"Dodge Ram","insurance":{"company":"ABC Insurance","policy_num":"12345"},"maintenance":[{"date":"08-27-2017","desc":"new tires"},{"date":"01-08-2018","desc":"oil change"}]}]
24 F Jane Roberts phone [{"type":"car","model":"Toyota Camry","insurance":{"company":"Car Insurance","policy_num":"98765"},"maintenance":[{"date":"05-11-2017","desc":"tires rotated"},{"date":"11-03-2017","desc":"oil change"}]},{"type":"car","model":"Honda Accord","insurance":{"company":"Car Insurance","policy_num":"98765"},"maintenance":[{"date":"10-07-2017","desc":"new air filter"},{"date":"01-13-2018","desc":"new brakes"}]}]

メリットと考慮事項

Document モデルを使用すると、JSON ストアまたはサービスのすべてのトップレベルデータと集約された配列データを単一のテーブルで確認できます。シンプルなクエリを送信してトップレベルデータを操作できます。クエリごとに JSON データの読み取りと解析のリクエストが1回だけ実行されるため、高速なパフォーマンスとストリーミング機能との優れた互換性が得られます。考慮すべき点としては、配列に格納されているデータへのニーズと、お使いのツールやアプリケーションが JSON 配列を意味のある形で処理できるかどうかがあります。

Flattened Documents モデリング



JSON データ全体に簡単にアクセスしたいユーザーには、データを単一のテーブルにフラット化するのが最適な選択肢です。JSON データ内の JSON パスに基づいて、ドライバーを単一のテーブルを解析するように設定できます。このモードでは、ネストしたオブジェクト配列は別のテーブルとして扱われますが、親テーブルに暗黙的に JOIN されます。ドライバーはストリーミングを使用し、クエリごとに JSON データを1回だけ解析します。Flattened Documents モデルでは、ドット表記を使用して JSON データ内のネストした要素にドリルダウンすることで、データに対して暗黙的な JOIN 文を実行できます。

以下は、上記のサンプルドキュメントに基づいたサンプルクエリとその結果です。JSON パス "$.people"、"$.people.vehicles"、"$.people.vehicles.maintenance" に基づいて解析します(これにより "people" コレクションと "vehicles" コレクションが暗黙的に JOIN され、"vehicles" コレクションと "maintenance" コレクションが暗黙的に JOIN されます)。

接続文字列

Data Model 接続プロパティを "FlattenedDocuments" に設定し、JSON Path 接続プロパティを "$.people;$.people.vehicles;$.people.vehicles.maintenance;" に設定すると、上記のクエリを実行してサンプル結果セットを確認できます。

DataModel=FlattenedDocuments;JSONPath='$.people;$.people.vehicles;$.people.vehicles.maintenance;'

メタデータ

以下のテーブルは、Flattened Documents データモデルを使用した場合のメタデータを示しています。

People
カラム データ型
people:_id String
personal.age Integer
personal.gender String
personal.name.first String
personal.name.last String
source String
vehicle:_id String
type String
model String
insurance.company String
insurance.policy_num String
maintenance:_id String
date Date
desc String

クエリ

このクエリでは、各 "people" オブジェクト内のネストした要素にドリルダウンできます。"vehicles" コレクションを JSON パスとして含めたので、"vehicle" の要素を明示的にクエリできます。

SELECT
  [personal.age] AS age,
  [personal.gender] AS gender,
  [personal.name.first] AS name_first,
  [personal.name.last] AS name_last,
  [source],
  [type],
  [model],
  [insurance.company] AS ins_company,
  [insurance.policy_num] AS ins_policy_num,
  [date] AS maint_date,
  [desc] AS maint_desc
FROM
  [people]

結果

記述されたパスに基づく水平・垂直フラット化により、各 "vehicle" オブジェクトはその親 "people" オブジェクトに暗黙的に JOIN され、各 "maintenance" オブジェクトはその親 "vehicle" オブジェクトに暗黙的に JOIN されます。結果として8行のテーブルが生成されます(2人の "people" それぞれに対して2つの "vehicles"、各 "vehicle" に対して2つの "maintenance" オブジェクト)。

age gender first_name last_name source type model ins_company ins_policy_num maint_date maint_desc
20 M John Doe internet car Honda Civic ABC Insurance 12345 2017-07-17 oil change
20 M John Doe internet car Honda Civic ABC Insurance 12345 2018-01-03 new tires
20 M John Doe internet truck Dodge Ram ABC Insurance 12345 2017-08-27 new tires
20 M John Doe internet truck Dodge Ram ABC Insurance 12345 2018-01-08 oil change
24 F Jane Roberts phone car Toyota Camry Car Insurance 98765 2017-05-11 tires rotated
24 F Jane Roberts phone car Toyota Camry Car Insurance 98765 2017-11-03 oil change
24 F Jane Roberts phone car Honda Accord Car Insurance 98765 2017-10-07 new air filter
24 F Jane Roberts phone car Honda Accord Car Insurance 98765 2018-01-13 new brakes

メリットと考慮事項

Flattened Documents を使用すると、JSON ストアまたはサービスのすべてのデータを単一のテーブルで確認できます。シンプルなクエリを送信して階層データにドリルダウンできます。クエリごとに JSON データの読み取りと解析のリクエストが1回だけ実行されるため、高速なパフォーマンスとストリーミング機能との優れた互換性が得られます。Flattened Documents を使用する際は、お使いのツールやアプリケーションが、個別のエンティティと事前に JOIN されたデータセットのどちらとより相性が良いかを考慮する必要があります。

Relational モデリング



CData ドライバーは、JSON ファイルまたはソース内のデータのリレーショナルモデルを作成するように設定でき、ネストしたオブジェクト配列を親テーブルとのリレーションシップを含む個別のテーブルとして扱います。これは、リレーショナルデータモデルを前提とする既存の BI、レポーティング、ETL ツールで JSON データを操作する必要がある場合に特に便利です。解釈されるモデルは、テーブルとして表示したい各オブジェクト配列のデータ内の JSON パスに基づいています。リレーショナルモデルを構築すると、JOIN クエリを実行するたびに、クエリに含まれる各「テーブル」に対して JSON ファイルまたはソースが1回ずつクエリされます。

以下は、上記のサンプルドキュメントに基づいたサンプルクエリとその結果です。JSON パス "$.people"、"$.people.vehicles"、"$.people.vehicles.maintenance" に基づくリレーショナルモデルを使用しています。

接続文字列

Data Model 接続プロパティを "Relational" に設定し、JSON Path 接続プロパティを "$.people;$.people.vehicles;$.people.vehicles.maintenance;" に設定すると、上記のクエリを実行してサンプル結果セットを確認できます。

DataModel=Relational;JSONPath='$.people;$.people.vehicles;$.people.vehicles.maintenance;'

メタデータ

以下のテーブルは、Relational データモデルを使用した場合のメタデータを示しています。

People
カラム データ型
_id String
personal.age Integer
personal.gender String
personal.name.first String
personal.name.last String
source String

Vehicles
カラム データ型
_id String
insurance.company String
insurance.policy_num String
model String
type String

Maintenance
カラム データ型
_id String
date Date
desc String


クエリ

このクエリでは、"people"、"vehicles"、"maintenance" テーブルを明示的に JOIN しています。

SELECT
  [people].[personal.age] AS age,
  [people].[personal.gender] AS gender,
  [people].[personal.name.first] AS first_name,
  [people].[personal.name.last] AS last_name,
  [people].[source],
  [vehicles].[type],
  [vehicles].[model],
  [vehicles].[insurance.company] AS ins_company,
  [vehicles].[insurance.policy_num] AS ins_policy_num,
  [maintenance].[date] AS maint_date,
  [maintenance].[desc] AS maint_desc
FROM
  [people]
JOIN
  [vehicles]
ON
  [people].[_id] = [vehicles].[people_id]
JOIN
  [maintenance]
ON
  [vehicles].[_id] = [maintenance].[vehicles_id]

結果

リレーショナルモデルを使用すると、JOIN はすべてクエリによって制御されます。この例では、各 "maintenance" オブジェクトがその親 "vehicle" オブジェクトに JOIN され、さらにその親 "people" オブジェクトに JOIN されて8行のテーブルが生成されます(2人の "people" それぞれに対して2つの "vehicles"、各 "vehicle" に対して2つの "maintenance" エントリ)。

age gender first_name last_name source type model ins_company ins_policy_num maint_date maint_desc
20 M John Doe internet car Honda Civic ABC Insurance 12345 2017-07-17 oil change
20 M John Doe internet car Honda Civic ABC Insurance 12345 2018-01-03 new tires
20 M John Doe internet truck Dodge Ram ABC Insurance 12345 2017-08-27 new tires
20 M John Doe internet truck Dodge Ram ABC Insurance 12345 2018-01-08 oil change
24 F Jane Roberts phone car Toyota Camry Car Insurance 98765 2017-05-11 tires rotated
24 F Jane Roberts phone car Toyota Camry Car Insurance 98765 2017-11-03 oil change
24 F Jane Roberts phone car Honda Accord Car Insurance 98765 2017-10-07 new air filter
24 F Jane Roberts phone car Honda Accord Car Insurance 98765 2018-01-13 new brakes

メリットと考慮事項

Relational モデリングを使用すると、JSON データまたはサービス内の個別のエンティティに基づいてデータのモデルを構築でき、一部の BI、レポーティング、ETL ツールとの互換性が向上します。ただし、リレーショナルモデルを構築してクエリを実行するには、パフォーマンスを犠牲にする必要があります。リレーショナルモデル内の複数のテーブルからデータを操作する場合、ドライバーはクエリ内の各テーブルに対してデータのクエリと解析を実行します。たとえば、上記のクエリには3回のリクエストが必要です。

関連記事



始める準備はできましたか?

JSON 用ドライバーの詳細、または無料トライアルをダウンロード:

今すぐダウンロード