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]]);
エンジンパラメータ
| パラメータ | 説明 |
|---|
host:port | MongoDB サーバーのアドレス。 |
database | リモートデータベース名。 |
collection | リモートコレクション名。 |
user | MongoDB ユーザー。 |
password | ユーザーのパスワード。 |
options | 任意。URL 形式の文字列として指定する MongoDB の接続文字列オプション。例: 'authSource=admin&ssl=true' |
oid_columns | WHERE 句で oid として扱うカラムのカンマ区切りリスト。デフォルトは _id です。 |
MongoDB Atlas のクラウド版を使用している場合、接続 URL は ‘Atlas SQL’ オプションから取得できます。
シードリスト(mongodb**+srv**) はまだサポートされていませんが、今後のリリースで追加される予定です。
あるいは、URI を指定することもできます:
ENGINE = MongoDB(uri, collection[, oid_columns]);
エンジンパラメータ
| Parameter | Description |
|---|
uri | MongoDBサーバーの接続URI。 |
collection | リモートコレクションの名前。 |
oid_columns | WHERE 句で oid として扱うカラムのカンマ区切りリスト。デフォルトは _id です。 |
| MongoDB | ClickHouse |
|---|
| bool, int32, int64 | Decimals を除く任意の数値型, Boolean, String |
| double | Float64, String |
| date | Date, Date32, DateTime, DateTime64, String |
| string | String, 正しくフォーマットされていれば Decimals を除く任意の数値型 |
| document | String (JSON として) |
| array | Array, String (JSON として) |
| oid | String |
| binary | カラム内では String、array または document 内では base64 エンコードされた文字列 |
| uuid (binary subtype 4) | UUID |
| any other | String |
MongoDB ドキュメント内にキーが見つからない場合 (たとえばカラム名が一致しない場合) 、デフォルト値または NULL (カラムが Nullable の場合) が挿入されます。
String をWHERE句で oid として扱いたい場合は、そのカラム名をテーブルエンジンの最後の引数に指定するだけです。
これは、MongoDB では _id カラムがデフォルトで 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"}
}
]
デフォルトでは、oid カラムとして扱われるのは _id のみです。
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_column を oid 型として認識していないためです。では、これを修正しましょう:
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 側での処理が発生する可能性があります。
Mongo では厳密な型のフィルターが必要なため、リテラルの型は常に明示的に指定することをおすすめします。
たとえば、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')
これは Date、Date32、DateTime、Bool、UUID に当てはまります。
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: A young man is accidentally sent 30 years into the past in a time-traveling DeLorean invented by his friend, Dr. Emmett Brown, and must make sure his high-school-age parents unite in order to save his own existence.
genres: ['Adventure','Comedy','Sci-Fi']
directors: ['Robert Zemeckis']
released: 1985-07-03
Row 2:
──────
title: Back to the Future Part II
plot: After visiting 2015, Marty McFly must repeat his visit to 1955 to prevent disastrous changes to 1985... without interfering with his first trip.
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;
┌─title──────────────────┬─rating─┐
1. │ No Country for Old Men │ 8.1 │
2. │ The Sunset Limited │ 7.4 │
3. │ The Road │ 7.3 │
└────────────────────────┴────────┘
生成された MongoDB クエリは、DEBUG レベルのログで確認できます。
実装の詳細については、mongocxx と mongoc のドキュメントを参照してください。