メインコンテンツへスキップ
メインコンテンツへスキップ

MongoDB テーブルエンジン

MongoDB エンジンは、リモートの MongoDB コレクションからデータを読み取るための、読み取り専用のテーブルエンジンです。

MongoDB v3.6 以降のサーバーのみがサポートされています。 シードリスト(mongodb+srv は現在サポートされていません。

テーブルを作成する

CREATE TABLE [IF NOT EXISTS] [db.]table_name
(
    name1 [type1],
    name2 [type2],
    ...
) ENGINE = MongoDB(host:port, database, collection, user, password[, options[, oid_columns]]);

エンジンパラメータ

ParameterDescription
host:portMongoDB サーバーのアドレス。
databaseリモートデータベース名。
collectionリモートコレクション名。
userMongoDB ユーザー。
passwordユーザーのパスワード。
optionsオプション。URL 形式の文字列として指定する MongoDB 接続文字列の options。例: 'authSource=admin&ssl=true'
oid_columnsWHERE 句で oid として扱う列のカンマ区切りリスト。デフォルトは _id
ヒント

MongoDB Atlas のクラウドサービスを使用している場合、接続 URL は「Atlas SQL」オプションから取得できます。 シードリスト(mongodb+srv)はまだサポートされていませんが、今後のリリースで追加される予定です。

別の方法として、URI を渡すこともできます。

ENGINE = MongoDB(uri, collection[, oid_columns]);

エンジンパラメータ

パラメータ説明
uriMongoDB サーバーの接続 URI。
collectionリモートコレクション名。
oid_columnsWHERE 句で oid として扱う列をカンマ区切りで指定します。既定では _id です。

型マッピング

MongoDBClickHouse
bool, int32, int64Decimals を除く任意の数値型、Boolean、String
doubleFloat64、String
dateDate、Date32、DateTime、DateTime64、String
stringString、正しくフォーマットされていれば任意の数値型 (Decimals を除く)
documentString(JSON として)
arrayArray、String(JSON として)
oidString
binaryカラム内では String、配列または document 内では base64 エンコードされた文字列
uuid (binary subtype 4)UUID
その他すべてString

キーが MongoDB ドキュメント内に存在しない場合 (たとえばカラム名が一致しない場合)、デフォルト値または (カラムが Nullable の場合は) NULL が挿入されます。

OID

WHERE 句で Stringoid として扱いたい場合は、テーブルエンジンの最後の引数にそのカラム名を指定します。 これは、MongoDB でデフォルトで oid 型を持つ _id カラムでレコードをクエリする際に必要になる場合があります。 テーブル内の _id フィールドが、たとえば uuid のような別の型である場合は、空の oid_columns を指定しなければなりません。指定しない場合、このパラメータのデフォルト値である _id が使用されます。

db.sample_oid.insertMany([
    {"another_oid_column": ObjectId()},
]);

db.sample_oid.find();
[
    {
        "_id": {"$oid": "67bf6cc44ebc466d33d42fb2"},
        "another_oid_column": {"$oid": "67bf6cc40000000000ea41b1"}
    }
]

既定では、_id のみが oid 列として扱われます。

CREATE TABLE sample_oid
(
    _id String,
    another_oid_column String
) ENGINE = MongoDB('mongodb://user:pass@host/db', 'sample_oid');

SELECT count() FROM sample_oid WHERE _id = '67bf6cc44ebc466d33d42fb2'; --1を出力します。
SELECT count() FROM sample_oid WHERE another_oid_column = '67bf6cc40000000000ea41b1'; --0を出力します。

この場合、出力は 0 になります。ClickHouse は another_oid_columnoid 型であることを認識していないためです。では、次のように修正しましょう:

CREATE TABLE sample_oid
(
    _id String,
    another_oid_column String
) ENGINE = MongoDB('mongodb://user:pass@host/db', 'sample_oid', '_id,another_oid_column');

-- または

CREATE TABLE sample_oid
(
    _id String,
    another_oid_column String
) ENGINE = MongoDB('host', 'db', 'sample_oid', 'user', 'pass', '', '_id,another_oid_column');

SELECT count() FROM sample_oid WHERE another_oid_column = '67bf6cc40000000000ea41b1'; -- 1が出力されます

サポートされている句

単純な式を含むクエリのみがサポートされます(例: WHERE field = <constant> ORDER BY field2 LIMIT <constant>)。 このような式は MongoDB のクエリ言語に変換され、サーバー側で実行されます。 mongodb_throw_on_unsupported_query を使用して、これらの制限をすべて無効化できます。 その場合、ClickHouse は可能な限り最善を尽くしてクエリを変換しようとしますが、テーブル全体のスキャンや ClickHouse 側での処理が発生する可能性があります。

注記

MongoDB では厳密な型付きフィルタが必要となるため、リテラルの型を明示的に設定することを常に推奨します。
例えば、Date 型でフィルタリングしたい場合:

SELECT * FROM mongo_table WHERE date = '2024-01-01'

これは、Mongo が文字列を Date にキャストしないため動作しません。そのため、手動でキャストする必要があります。

SELECT * FROM mongo_table WHERE date = '2024-01-01'::Date OR date = toDate('2024-01-01')

これは DateDate32DateTimeBoolUUID の各型に適用されます。

使用例

MongoDB に sample_mflix データセットが読み込まれていることを前提とします

MongoDB コレクション内のデータを読み取るための ClickHouse テーブルを作成します:

CREATE TABLE sample_mflix_table
(
    _id String,
    title String,
    plot String,
    genres Array(String),
    directors Array(String),
    writers Array(String),
    released Date,
    imdb String,
    year String
) ENGINE = MongoDB('mongodb://<USERNAME>:<PASSWORD>@atlas-sql-6634be87cefd3876070caf96-98lxs.a.query.mongodb.net/sample_mflix?ssl=true&authSource=admin', 'movies');

クエリ:

SELECT count() FROM sample_mflix_table
   ┌─count()─┐
1. │   21349 │
   └─────────┘
-- JSONExtractStringはMongoDBにプッシュダウンできません
SET mongodb_throw_on_unsupported_query = 0;

-- 評価が7.5より大きい「バック・トゥ・ザ・フューチャー」の続編をすべて検索
SELECT title, plot, genres, directors, released FROM sample_mflix_table
WHERE title IN ('Back to the Future', 'Back to the Future Part II', 'Back to the Future Part III')
    AND toFloat32(JSONExtractString(imdb, 'rating')) > 7.5
ORDER BY year
FORMAT Vertical;
Row 1:
──────
title:     Back to the Future
plot:      若い男性が友人のエメット・ブラウン博士が発明したタイムトラベル可能なデロリアンで誤って30年前の過去に送られ、自分の存在を守るために高校生時代の両親を結びつけなければならない。
genres:    ['Adventure','Comedy','Sci-Fi']
directors: ['Robert Zemeckis']
released:  1985-07-03

Row 2:
──────
title:     Back to the Future Part II
plot:      2015年を訪れた後、マーティ・マクフライは1985年への壊滅的な変化を防ぐために、最初の旅行に干渉することなく1955年を再訪しなければならない。
genres:    ['Action','Adventure','Comedy']
directors: ['Robert Zemeckis']
released:  1989-11-22
-- Cormac McCarthyの著書を原作とする映画の上位3作品を検索
SELECT title, toFloat32(JSONExtractString(imdb, 'rating')) AS rating
FROM sample_mflix_table
WHERE arrayExists(x -> x LIKE 'Cormac McCarthy%', writers)
ORDER BY rating DESC
LIMIT 3;
   ┌─タイトル───────────────┬─評価───┐
1. │ ノーカントリー         │    8.1 │
2. │ サンセット・リミテッド │    7.4 │
3. │ ザ・ロード             │    7.3 │
   └────────────────────────┴────────┘

トラブルシューティング

DEBUG レベルのログで生成された MongoDB クエリを確認できます。

実装の詳細については、mongocxx および mongoc のドキュメントを参照してください。