MongoDBエラーの解決方法: 'text index required for $text query'

intermediate🍃 MongoDB2026-07-15| MongoDB (全バージョン), Node.js (Mongoose/MongoDB Driver), Python (PyMongo), MongoDB Shell

Error Message

MongoServerError: text index required for $text query
#mongodb#mongoose#database-indexing#full-text-search

問題の発生MongoDBで$text演算子を使用して全文検索を実行しようとした際に、結果の代わりに赤文字のエラーが表示されることがあります。通常、以下のようなエラーメッセージが表示されます。

MongoServerError: text index required for $text query

私は最近、ドキュメントサイトの検索バーを構築しているときにこの問題に遭遇しました。タイトルと本文の両方からキーワードを見つけるために、次のようなクエリを使用しました。

db.articles.find({ $text: { $search: "パフォーマンスの最適化" } })

一見正しく動作するように見えますが、MongoDBは全文検索を標準的なフィールド検索とは異なる方法で処理します。{ status: "active" }のようなクエリは、インデックスがなくても(低速ながら)実行可能ですが、$textクエリはテキストインデックスを定義しない限り、物理的に実行することができません。

エラーの原因内部では、$text演算子が複雑な処理を行っています。ステミング(「running」を「run」に変換するなど)を実行し、「the」や「and」などのストップワードを除去し、文字列をトークン化します。これらを効率的に行うために、MongoDBは専用のデータ構造を必要とします。データベースに対して、どのフィールドをこの構造に含めるかを指定していない場合、参照すべきマップが存在しないため、処理を断念してエラーをスローします。

ステップバイステップの解決策### 1. 既存のインデックスを確認するまず、現在どのようなインデックスが存在するかを確認します。MongoDB Shell (mongosh) で以下のコマンドを実行してください。

db.articles.getIndexes()

結果を確認してください。値が"text"となっているキーが見当たらない場合、それが原因です。_id_categoryに対するインデックスは表示されるかもしれませんが、それらはテキスト検索には利用できません。

2. テキストインデックスを作成する検索対象とするフィールドをMongoDBに明示的に伝える必要があります。titlecontentの両方のフィールドを検索したい場合は、次のコマンドを実行します。

db.articles.createIndex({ 
  title: "text", 
  content: "text" 
})

MongoDB 4.2以降では、この処理はデフォルトでバックグラウンドで実行されます。データベースをロックすることはありませんが、I/Oを消費します。100万件の小さなドキュメントを含むコレクションの場合、ハードウェアの性能にもよりますが、30秒から60秒ほどかかる場合があります。

3. すべてを検索するワイルドカードプロトタイプを作成中で、すべての文字列フィールドを個別に指定せずに検索したい場合は、ワイルドカード指定子を使用できます。

db.collection.createIndex({ "$**": "text" })

この方法は慎重に使用してください。ワイルドカードによるテキストインデックスは、ドキュメント内のすべての文字列をインデックス化するため、ストレージ使用量が30%以上増加する可能性があります。

Mongoose (Node.js) での修正Mongooseを使用している場合は、シェルで修正するだけでなく、本番環境へのデプロイ時にインデックスが維持されるようSchemaを更新する必要があります。以下はクリーンな設定方法です。

const articleSchema = new mongoose.Schema({
  title: String,
  content: String,
  author: String
});

// スキーマレベルでテキストインデックスを定義
articleSchema.index({ title: 'text', content: 'text' });

const Article = mongoose.model('Article', articleSchema);

注意: Mongooseはアプリの起動時にインデックスを作成します。そのコレクションにすでに別のインデックスが存在する場合、Mongooseは新しいインデックスの作成に静かに失敗することがあります。エラーが解消されない場合は、シェルでdb.articles.dropIndexes()を実行して既存のインデックスを削除し、Nodeサーバーを再起動してください。

「インデックスは1つ」のルールよくある罠は、複数のテキストインデックスを作成しようとすることです。MongoDBでは、1つのコレクションにつき1つのテキストインデックスしか許可されません。次のように2つの別々のコマンドを実行しようとすると、2つ目は失敗します。

db.posts.createIndex({ title: "text" })
db.posts.createIndex({ description: "text" }) // エラー!

両方のフィールドを検索対象にするには、ステップ2で示したように、それらを1つの複合インデックスにまとめる必要があります。

修正の確認方法インデックスを作成した後、クエリが実際にそれを使用しているかを確認します。クエリの末尾に.explain("executionStats")を追加してください。

db.articles.find({ $text: { $search: "データベース" } }).explain("executionStats")

出力結果の中でwinningPlanを確認してください。TEXT_MATCHというステージがあれば、設定は完了です。エラーは消え、検索結果が即座に表示されるはずです。

重要なポイント- ストレージコスト: テキストインデックスは、標準的なB-treeインデックスよりも大幅にサイズが大きくなります。RAMとディスクの使用量が大幅に増加することを想定してください。- 重み付け: 重みを割り当てることで、titlebodyよりも重要視させることができます(例:{ title: "text", content: "text" }, { weights: { title: 10, content: 2 } })。- 言語: MongoDBのデフォルト設定は英語です。コンテンツがフランス語やスペイン語などの場合は、インデックスのオプションでdefault_languageを指定して、ステミングが正しく機能するようにしてください。

Related Error Notes