問題の概要MongoDBがWiredTigerストレージエンジンの1,024バイト制限を超えるフィールドにインデックスを張ろうとすると、このエラーが発生します。通常、既存のコレクションに対するcreateIndex()操作中に発生します。また、2,000文字のURLやBase64エンコードされた画像文字列など、長い文字列をインデックス済みのフィールドに挿入しようとした際にも発生します。
正確なエラーメッセージは以下の通りです:
WiredTigerIndex::insert: key too large to index, failing 1024 { : "..." }
MongoDB 4.2より前のバージョンでは、この制限は厳格な壁となります。インデックス対象の単一フィールドが1,025バイトに達すると、書き込み操作やインデックスの作成は直ちに失敗します。
問題のあるドキュメントを特定するスキーマを修正する前に、ルールに違反している特定のドキュメントを見つける必要があります。集計フレームワーク(Aggregation Framework)を使用して、問題のフィールドのバイト長を計算します。以下は、1,000バイトを超えるフィールドを検索するスクリプトです:
db.your_collection.aggregate([
{ $project: { field_length: { $strLenBytes: "$yourField" }, yourField: 1 } },
{ $match: { field_length: { $gt: 1000 } } },
{ $sort: { field_length: -1 } }
])
バイトと文字数を混同しないでください。標準的な「A」は1バイトですが、🚀のような絵文字は1つで4バイトを消費します。つまり、わずか256個の絵文字の文字列でも、1,024バイトのエラーを誘発します。
解決策### 1. ハッシュインデックスを使用する特定の長いURLを検索する場合のように、完全一致(Equality matches)のみが必要な場合は、ハッシュインデックスが最適です。巨大な文字列そのものをインデックスする代わりに、MongoDBは値の固定サイズのハッシュをインデックスします。これにより、1,024バイトの制限を完全に回避できます。
// 最初に失敗しているB-treeインデックスを削除します
db.your_collection.dropIndex("yourField_1")
// 代わりにハッシュインデックスを作成します
db.your_collection.createIndex({ yourField: "hashed" })
2. テキストインデックスを使用する値の完全一致ではなく、文字列内のキーワードを検索する必要がある場合は、textインデックスに切り替えます。テキストインデックスは文字列を個々のトークンに分解します。各トークンは通常小さいため、フィールド全体として1,024バイトの制限に抵触することはありません。
db.your_collection.createIndex({ yourField: "text" })
3. レガシーな回避策(MongoDB 4.0以下)すぐにインデックスの種類を変更できない場合は、サイズが大きすぎるドキュメントのインデックス作成を単にスキップするようにMongoDBに指示できます。これによりデータベースがエラーをスローするのを防げますが、注意点があります。それらのドキュメントはそのインデックスを使用するクエリの結果には表示されなくなります。
db.getSiblingDB("admin").runCommand({
setParameter: 1,
failIndexKeyTooLong: false
})
MongoDB 4.2ではこのパラメーターが削除されたことに注意してください。新しいバージョンでは、大きなキーをデフォルトでより適切に処理しますが、依然としてパフォーマンス上のペナルティは存在します。
4. コード内でデータをハッシュ化する完全一致が必要だが、パフォーマンスのために標準のB-treeインデックスを維持したい場合があります。この場合、保存する前にアプリケーションロジックでフィールドをハッシュ化(SHA-256などを使用)します。この64文字のハッシュを別のフィールドに保存し、そちらにインデックスを張ります。
// Node.jsの例
const crypto = require('crypto');
const longValue = "...非常に長い文字列...";
const hashedValue = crypto.createHash('sha256').update(longValue).digest('hex');
db.collection.insertOne({
original_field: longValue,
field_hash: hashedValue
});
// 固定長の小さなハッシュにインデックスを張る
db.collection.createIndex({ field_hash: 1 });
検証修正を適用したら、インデックスが実際に使用されているか確認します。一般的なクエリに対してexplain()を実行し、実行計画を確認してください:
db.your_collection.find({ yourField: "検索する値" }).explain("executionStats")
winningPlanを確認してください。ハッシュインデックスを使用した場合、stageはIXSCANになっているはずです。nReturnedを再確認して、クエリが期待通りのドキュメントを見つけているかチェックしてください。

