メインコンテンツへスキップ
このガイドでは、ClickPipes 経由で MongoDB から ClickHouse にレプリケートされた JSON データを扱う際の一般的なパターンを紹介します。 たとえば、顧客の注文を追跡するためのコレクション t1 を MongoDB に作成したとします。
MongoDB CDC コネクタは、ネイティブの JSON データ型を使用して、MongoDB のドキュメントを ClickHouse にレプリケートします。ClickHouse のレプリケートテーブル t1 には、次の行が含まれます。

テーブルスキーマ

レプリケートテーブルでは、以下の標準スキーマを使用します。
  • _id: MongoDB の主キー
  • doc: JSON データ型としてレプリケートされた MongoDB ドキュメント
  • _peerdb_synced_at: 行が最後に同期された時刻を記録します
  • _peerdb_version: 行のバージョンを追跡します。行が更新または削除されるとインクリメントされます
  • _peerdb_is_deleted: 行が削除済みかどうかを示します

ReplacingMergeTree テーブルエンジン

ClickPipes は、ReplacingMergeTree テーブルエンジンファミリーを使用して、MongoDB のコレクションを ClickHouse にマッピングします。このエンジンでは、更新は、特定の主キー (_id) に対応する、より新しいバージョン (_peerdb_version) のドキュメントを insert する形で表現されます。これにより、更新、置換、削除をバージョン付き insert として効率的に処理できます。 ReplacingMergeTree は、バックグラウンドで非同期に重複を削除します。同じ行の重複がないことを保証するには、FINAL 修飾子 を使用します。例:

削除の扱い

MongoDB で削除されたデータは、_peerdb_is_deleted カラムに削除済みの印が付いた新しい行として伝播されます。通常、クエリではこれらを除外します。
各クエリで毎回フィルタを指定する代わりに、削除済みの行を自動的に除外する行レベルポリシーを作成することもできます。

JSONデータのクエリ

ドット記法を使うと、JSONフィールドを直接クエリできます。
Query
Result
ドット構文を使ってネストされたオブジェクトのフィールドをクエリする場合は、^ 演算子を必ず追加してください。
Query
Result

Dynamic 型

ClickHouse では、JSON の各フィールドは Dynamic 型になります。Dynamic 型を使うと、ClickHouse は型を事前に把握していなくても、どのような型の値でも格納できます。これは toTypeName 関数で確認できます。
Query
Result
フィールドの実際のデータ型を確認するには、dynamicType 関数を使います。同じフィールド名でも、行によってデータ型が異なる場合がある点に注意してください。
Query
Result
通常の関数は、通常のカラムと同様に Dynamic 型でも使用できます。 例 1: 日付のパース
Query
Result
例 2: 条件分岐
Query
Result
例 3: Arrayの操作
Query
Result

フィールドの型変換

ClickHouse の集約関数は、Dynamic 型を直接扱えません。たとえば、Dynamic 型に対して sum 関数を直接使用しようとすると、次のエラーが発生します。
集約関数を使用するには、CAST 関数または :: 構文を使って、フィールドを適切な型にキャストします。
Query
Result
Dynamic型から基になるデータ型 (dynamicType によって決まる型) へのキャストは非常に高速です。これは、ClickHouse が値を内部的にすでにその基の型で保持しているためです。

JSONのフラット化

通常のビュー

JSONテーブルの上に通常のビューを作成すると、フラット化、CAST、変換のロジックをカプセル化し、リレーショナルテーブルのようにデータをクエリできるようになります。通常のビューは、基になるデータではなくクエリ自体のみを保存するため、軽量です。たとえば、次のようになります。
このビューのスキーマは次のとおりです:
これで、フラット化されたテーブルに対するのと同じように、このビューにクエリを実行できます。

リフレッシャブルmaterialized view

リフレッシュ可能なマテリアライズドビュー を作成できます。これにより、行の重複を排除し、その結果をフラット化した宛先テーブルに保存するクエリの実行をスケジュールできます。スケジュールされた更新が実行されるたびに、宛先テーブルは最新のクエリ結果で置き換えられます。 この方法の主な利点は、FINAL キーワードを使用するクエリが更新時に一度だけ実行されることです。これにより、その後に宛先テーブルに対して実行するクエリで FINAL を使う必要がなくなります。 一方で、宛先テーブル内のデータは直近の更新時点の内容に限られるという欠点があります。多くのユースケースでは、更新間隔を数分から数時間に設定することで、データ鮮度とクエリ性能のバランスを適切に取ることができます。
これで、FINAL修飾子を使わずに、テーブル flattened_t1 に直接クエリできるようになりました:

インクリメンタルmaterialized view

フラット化されたカラムにリアルタイムでアクセスしたい場合は、インクリメンタルmaterialized viewを作成できます。テーブルが頻繁に更新される場合は、更新のたびにマージがトリガーされるため、materialized view で FINAL modifier を使用することは推奨されません。代わりに、materialized view の上に通常のビューを作成することで、クエリ時にデータを重複排除できます。
これで、次のようにビュー flattened_t1_final に対してクエリを実行できます:
最終更新日 2026年7月1日