OSSドキュメントDB比較:MongoDB vs CouchDB vs SurrealDB でドキュメントDBを選ぶ
オープンソースラボ編集部 ・ 2026年6月14日
OSSドキュメントDB比較:MongoDB vs CouchDB vs SurrealDB でドキュメントDBを選ぶ
MySQLやPostgreSQLのようなリレーショナルDBでは扱いにくい可変スキーマ・ネストしたドキュメント・JSONデータの管理には、ドキュメント指向NoSQLデータベースが適しています。MongoDB(世界最大シェアNoSQL)・CouchDB(Apache製・マルチマスターレプリケーション)・SurrealDB(多モデル・GraphQL・リアルタイム・次世代)の3つが2026年のOSSドキュメントDB主要選択肢です。
ドキュメントDBを使う理由
- 可変スキーマ: ユーザーごとに異なる属性・プロパティ(SNSプロフィール・商品カタログ)をスキーマなしで格納
- JSONネイティブ: フロントエンドとバックエンド間のJSONデータを変換なしに保存・取得
- 水平スケール: リレーショナルDBのような複雑なJOINなしにシャーディングで水平スケール
- 組み込み配列: タグ・コメント・関連ID等の配列をカラムなしにドキュメント内に格納
主要ツールの概要
MongoDB
2009年公開(MongoDB Inc.)、C++製のOSSです。GitHubスター26k+。世界最大シェアNoSQLドキュメントDBで、SSPL v1ライセンスです。BSONドキュメント・インデックス・Aggregation Pipeline・Change Streams・Atlas Search(全文検索)・マルチドキュメントトランザクションが統合されています。
# docker-compose.yml: MongoDB 7 + mongo-express
version: "3.8"
services:
mongodb:
image: mongo:7
restart: unless-stopped
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASS}
volumes:
- mongo_data:/data/db
- ./mongo-init.js:/docker-entrypoint-initdb.d/init.js:ro
command: --wiredTigerCacheSizeGB 0.5 # メモリ制限(512MB)
mongo-express:
image: mongo-express:latest
restart: unless-stopped
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: admin
ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGO_PASS}
ME_CONFIG_MONGODB_URL: mongodb://admin:${MONGO_PASS}@mongodb:27017/
ME_CONFIG_BASICAUTH_USERNAME: meadmin
ME_CONFIG_BASICAUTH_PASSWORD: ${ME_PASS}
volumes:
mongo_data:
# Python: PyMongo でドキュメントCRUD・Aggregation Pipeline
from pymongo import MongoClient, ASCENDING, DESCENDING
from datetime import datetime, timedelta
from typing import Optional
client = MongoClient('mongodb://admin:password@localhost:27017/')
db = client['myapp']
articles = db['articles']
def create_article(title: str, content: str, tags: list, author_id: str) -> dict:
'''記事ドキュメントをMongoDBに作成'''
doc = {
'title': title,
'content': content,
'tags': tags,
'author_id': author_id,
'stats': {'views': 0, 'likes': 0},
'metadata': {'created_at': datetime.utcnow(), 'updated_at': datetime.utcnow()},
'published': False,
}
result = articles.insert_one(doc)
return {'id': str(result.inserted_id), **doc}
def search_articles_by_tag(tag: str, limit: int = 20) -> list:
'''タグで記事を検索(配列フィールドへの$inクエリ)'''
cursor = articles.find(
{'tags': {'$in': [tag]}, 'published': True},
projection={'content': 0} # contentを除外(軽量化)
).sort('metadata.created_at', DESCENDING).limit(limit)
return list(cursor)
def get_tag_ranking(days: int = 30) -> list:
'''過去N日間で最もよく使われたタグランキング(Aggregation Pipeline)'''
since = datetime.utcnow() - timedelta(days=days)
pipeline = [
{'$match': {'metadata.created_at': {'$gte': since}, 'published': True}},
{'$unwind': '$tags'}, # 配列を展開
{'$group': {'_id': '$tags', 'count': {'$sum': 1}, 'total_views': {'$sum': '$stats.views'}}},
{'$sort': {'count': DESCENDING}},
{'$limit': 20},
{'$project': {'tag': '$_id', 'count': 1, 'total_views': 1, '_id': 0}},
]
return list(articles.aggregate(pipeline))
# インデックス作成(パフォーマンス最適化)
articles.create_index([('tags', ASCENDING)])
articles.create_index([('metadata.created_at', DESCENDING)])
articles.create_index([('title', 'text'), ('content', 'text')]) # 全文検索インデックス
CouchDB
2005年公開(Apache Software Foundation)、Erlang製のOSSです。GitHubスター6k+。HTTPレストフルAPIで操作できるApache製ドキュメントDBで、マルチマスターレプリケーション(CouchDB Sync Protocol)が特徴です。オフラインファーストのアプリケーション開発(PouchDB→CouchDB同期)やIoTデバイスからのデータ収集に適しています。
# docker-compose.yml: CouchDB 3
version: "3.8"
services:
couchdb:
image: couchdb:3
restart: unless-stopped
ports:
- "5984:5984"
environment:
COUCHDB_USER: admin
COUCHDB_PASSWORD: ${COUCH_PASS}
volumes:
- couchdb_data:/opt/couchdb/data
volumes:
couchdb_data:
# Python: CouchDB HTTP REST API でドキュメント操作
import requests
COUCH_URL = 'http://admin:password@localhost:5984'
def create_database(db_name: str) -> dict:
'''CouchDBデータベース作成(PUT /db_name)'''
return requests.put(f'{COUCH_URL}/{db_name}').json()
def save_document(db_name: str, doc: dict, doc_id: Optional[str] = None) -> dict:
'''CouchDBにドキュメントを保存(PUT or POST)'''
if doc_id:
resp = requests.put(f'{COUCH_URL}/{db_name}/{doc_id}', json=doc)
else:
resp = requests.post(f'{COUCH_URL}/{db_name}', json=doc)
return resp.json()
def query_by_view(db_name: str, view_name: str, key: str = None) -> list:
'''CouchDBのViewクエリで集計データを取得'''
url = f'{COUCH_URL}/{db_name}/_design/mydesign/_view/{view_name}'
params = {'key': f'"{key}"'} if key else {}
resp = requests.get(url, params=params)
return resp.json().get('rows', [])
SurrealDB
2022年公開(Surreal)、Rust製のOSSです。GitHubスター28k+。SQL・GraphQL・ドキュメント・グラフ・時系列を1つのデータベースで扱える次世代多モデルDBで、WebSocketによるリアルタイムクエリ・Row-levelセキュリティ・埋め込みJavaScript関数・WASM等の機能を持ちます。
# docker-compose.yml: SurrealDB
version: "3.8"
services:
surrealdb:
image: surrealdb/surrealdb:latest
restart: unless-stopped
ports:
- "8000:8000"
command: start --log trace --user root --pass ${SURREAL_PASS} file:/mydata/mydb.db
volumes:
- surreal_data:/mydata
volumes:
surreal_data:
# Python: SurrealDB SDK でSurrealQLクエリ
from surrealdb import Surreal
async def surreal_demo():
async with Surreal('ws://localhost:8000/rpc') as db:
await db.signin({'user': 'root', 'pass': 'password'})
await db.use('myapp', 'mydb')
# レコード作成(ULIDが自動生成)
person = await db.create('person', {
'name': '山田太郎',
'email': 'taro@example.com',
'tags': ['developer', 'oss'],
})
# SurrealQL: JOINなしでグラフリレーション
await db.query('RELATE person:taro->follows->person:hanako')
# グラフトラバーサル(フォロー関係を2ホップで取得)
result = await db.query(
'SELECT ->follows->person.name AS following FROM person:taro FETCH following'
)
return result
機能比較表
| 比較項目 | MongoDB | CouchDB | SurrealDB |
|---|---|---|---|
| トランザクション | ✅ マルチドキュメント | △ | ✅ |
| グラフDBサポート | △ | ❌ | ✅ ネイティブ |
| オフライン同期 | △ | ✅ Sync Protocol | △ |
| リアルタイム | Change Streams | Changes Feed | ✅ WebSocket |
| GitHub Stars | 26k+ | 6k+ | 28k+ |
ドキュメントDBはDevOpsカテゴリ/categories/devopsの監視スタック(Prometheus/Grafana)と組み合わせてMongoDBのスロークエリ・インデックス使用率・WiredTigerキャッシュヒット率をメトリクスとして収集します。LLMツールカテゴリ/categories/llm-toolsのベクトルストア(pgvector/Chroma)とSurrealDBの多モデル特性を組み合わせてドキュメント・ベクトル・グラフを1つのDBでRAGパイプラインに活用します。
FAQ
Q. MongoDBのAggregation Pipelineで複雑な集計を実装するには?
A. $match→$group→$project→$sortの順でパイプラインを構築します。典型的なパターン: 時間別売上集計: $match(期間フィルタ)→$group: {_id: {$dateToString: {format: '%Y-%m-%d', date: '$created_at'}}, revenue: {$sum: '$amount'}}→$sort: {_id: 1}。ルックアップ(JOIN代替): $lookup: {from: 'users', localField: 'user_id', foreignField: '_id', as: 'user'}→$unwind: '$user'→$project: {'user.name': 1, revenue: 1}。ウィンドウ関数: $setWindowFieldsで累計売上・移動平均を計算(MongoDB 5.0+)。Explain: .explain('executionStats')でパイプラインの実行計画・COLLSCAN→IXSCANを確認してインデックスを最適化。
Q. CouchDBとPouchDBを使ったオフラインファーストアプリの実装方法は?
A. PouchDB(ブラウザ内DB)とCouchDBのSync Protocolを使って、オフライン状態でもデータ保存・オンライン復帰時に自動同期するアプリを構築できます。実装: ①npm install pouchdb pouchdb-find②ブラウザ側: const localDB = new PouchDB('myapp')→localDB.put({_id: 'doc-1', data: 'value'})でオフラインに書き込み③同期開始: localDB.sync('https://admin:pass@couchdb.example.com/myapp', {live: true, retry: true})→オンライン時に自動でCouchDBに同期④競合解決: CouchDBの_conflictsフィールドで競合を検出→ビジネスロジックで最新バージョンを選択。ユースケース: フィールドワーカー向けアプリ(電波が届かない場所でのデータ収集→事務所でPCをWiに繋いだ瞬間に自動同期)。
Q. SurrealDBでグラフリレーションを使ったソーシャルグラフを構築するには?
A. SurrealQLのRELATE文でグラフエッジを作成してJOINなしにグラフトラバーサルクエリを実行できます。フォロー関係: RELATE person:taro->follows->person:hanako SET created_at = time::now()でエッジ作成→SELECT ->follows.name FROM person:taroでフォロー中のユーザー名を取得。友達の友達(2ホップ): SELECT ->follows->follows.name AS friends_of_friends FROM person:taro WHERE ->follows->follows != person:taro。共通フォロワー: LET $a = (SELECT ->follows FROM person:taro).follows; LET $b = (SELECT ->follows FROM person:hanako).follows; SELECT * FROM $a INTERSECT $b。アクティビティフィード: SELECT in.*, out.title AS article_title FROM liked WHERE out.published = true ORDER BY created_at DESC LIMIT 20でフォロー中ユーザーのいいね活動をフィードとして取得。
Q. MongoDB・CouchDB・SurrealDBをどう使い分けるべきですか?
A. 大規模Webアプリ・豊富なエコシステム・Aggregation分析にはMongoDB、オフライン同期・HTTPファーストAPI・IoTデータ収集にはCouchDB、グラフ+ドキュメント+SQL統合・リアルタイム・新規プロジェクトにはSurrealDBが向いています。MongoDB優位: ①世界最大シェア→ドキュメント・サポート・ライブラリが豊富②Aggregation Pipelineで複雑な分析→BI/レポーティングに最適③Atlas(マネージド)への移行が容易→セルフホスト→クラウド移行に備えた構成が取りやすい④MongoDBのAtlas Searchで全文検索統合(Lucene/kNN)。CouchDB優位: ①HTTP REST APIがネイティブ→curlで直接操作②PouchDBとの同期で最高のオフラインファースト対応③マルチマスターレプリケーション→複数拠点への分散が容易。SurrealDB優位: ①SQL・GraphQL・ドキュメント・グラフを1DBで統合→マイクロサービスのDB数を削減②Row-levelセキュリティ→APIサーバーをバイパスしてフロントエンドから直接クエリできる③Rustベースで高速・低メモリ消費。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| 大規模・エコシステム・Aggregation分析 | MongoDB |
| オフライン同期・HTTP API・IoT | CouchDB |
| 多モデル・グラフ・リアルタイム・新規 | SurrealDB |