検索テキスト
Overview
$text
クエリ演算子を使用してテキスト検索を実行すると、コレクション内の string タイプのフィールドで、単語やフレーズを検索できます。 この演算子は、検索string内のスペースで区切られた各タームに対して論理 OR
を実行します。 また、サポートされている言語の大文字と小文字の区別、ストップワード、単語のステミング(複数形やその他の時制など)を取り扱うための追加のオプションを指定することもできます。 これは、トランスクリプト、エッセイ、ウェブページなどの非構造化テキストに特に便利です。
$text
クエリ演算子では、コレクションのテキスト インデックスに検索フィールドを指定する必要があります。テキスト インデックスの作成と、$text
クエリ演算子の使用に必要なサンプル コードについては、以下の例を参照してください。
注意
Atlas Searchを使用すると、MongoDB データを処理して高速で関連性ベースの検索機能を簡単に構築できます。 フルマネージド型のサービスとしてのデータベースであるMongoDB Atlasを今すぐお試しください。
例
次の例では、 sample_mflix
データベース内のmovies
コレクションのサンプル データを使用します。 title
フィールドでテキスト検索を有効にするには、次のコマンドを使用してテキスト インデックスを作成します。
db.movies.createIndex({ title: "text" });
このガイドの例では、単一フィールドのテキスト インデックスを使用していますが、複合テキスト インデックスを作成して、テキスト クエリを複数のフィールドに拡大することもできます。次のコマンドを実行すると、movies
コレクションの 2 つのフィールドにテキスト インデックスが作成されます。
db.movies.createIndex({ title: "text", plot: "text" });
Tip
テキスト インデックスでのフィールドの重みの指定
複合テキスト インデックスを作成するときに、重みオプションを指定してインデックス内の特定のテキスト フィールドに優先順位を付けることができます。テキスト検索を実行すると、フィールドの重みは、MongoDB が一致する各ドキュメントのテキスト検索スコアを計算する方法に影響します。
テキスト インデックスの作成時におけるフィールドの重みの指定方法の詳細については、「インデックス ガイド」のテキスト インデックスセクションを参照してください。
テキスト インデックスは、コレクションあたり 1つ のみ作成できます。各テキスト検索クエリでは、そのインデックスに指定されているすべてのフィールドでクエリを実行して一致を探します。
テキスト インデックスの詳細については、サーバー マニュアルの「テキストインデックス 」を参照してください。
単語の検索
この例では、「trek」という単語を含むタイトルを探すことで、映画「Star Trek」のクエリを実行します。複数の単語を使用してクエリを実行する場合は、単語をスペースで区切って、検索タームのいずれかに一致するドキュメントを検索します(論理演算子 OR
)。
const query = { $text: { $search: "trek" } }; // Return only the `title` of each matched document const projection = { _id: 0, title: 1, }; // find documents based on our query and projection const cursor = movies.find(query).project(projection);
この操作により次のドキュメントが返されます。
{ title: 'Trek Nation' } { title: 'Star Trek' } { title: 'Star Trek Into Darkness' } { title: 'Star Trek: Nemesis' } { title: 'Star Trek: Insurrection' } { title: 'Star Trek: Generations' } { title: 'Star Trek: First Contact' } { title: 'Star Trek: The Motion Picture' } { title: 'Star Trek VI: The Undiscovered Country' } { title: 'Star Trek V: The Final Frontier' } { title: 'Star Trek IV: The Voyage Home' } { title: 'Star Trek III: The Search for Spock' } { title: 'Star Trek II: The Wrath of Khan' }
成功!タイトルに「trek」という単語が含まれる movies
コレクション内のすべてのドキュメントがクエリで見つかりました。残念ながら、検索結果に意図しないアイテムが 1 つ含まれていました。「Trek Nation」はスタートレックに関する映画であり、映画シリーズ Star Trek には含まれません。より具体的なフレーズでクエリを実行すると、この問題を解決できます。
フレーズで検索
より具体的なクエリにするには、「trek」という単語だけでなく、「star trek」というフレーズを使用してみてください。フレーズで検索するには、複数の単語を含むフレーズをエスケープ文字が付いた引用符(\"<term>\"
)で囲みます。
const query = { $text: { $search: "\"star trek\"" } }; // Return only the `title` of each matched document const projection = { _id: 0, title: 1, }; // find documents based on our query and projection const cursor = movies.find(query).project(projection);
「trek」というタームだけでなく、「star trek」というフレーズでクエリを実行すると、次のドキュメントと一致します。
{ title: 'Star Trek' } { title: 'Star Trek Into Darkness' } { title: 'Star Trek: Nemesis' } { title: 'Star Trek: Insurrection' } { title: 'Star Trek: Generations' } { title: 'Star Trek: First Contact' } { title: 'Star Trek: The Motion Picture' } { title: 'Star Trek VI: The Undiscovered Country' } { title: 'Star Trek V: The Final Frontier' } { title: 'Star Trek IV: The Voyage Home' } { title: 'Star Trek III: The Search for Spock' } { title: 'Star Trek II: The Wrath of Khan' }
これらの結果には、「star trek」というフレーズを含むデータベース内のすべての映画が含まれます。この事例では、結果は架空の『スター トレック』映画のみになります。 残念ながら、このクエリはオリジナルの映画シリーズの一部ではない映画「Star Trek Into darkness」を返しました。 この問題を解決するには、そのドキュメントを除外して省略できます。
否定を含むクエリ
除外されたタームを使用するには、結果セットから省略するタームの前に負の記号( -
)を付けます。 クエリ操作は、このタームを含むドキュメントをすべて検索結果から除外します。 このクエリには 2 つの異なるタームが含まれているため、スペースで区切ります。
const query = { $text: { $search: "\"star trek\" -\"into darkness\"" } }; // Include only the `title` field of each matched document const projection = { _id: 0, title: 1, }; // find documents based on our query and projection const cursor = movies.find(query).project(projection);
否定的なタームを使用してクエリを実行すると、次のドキュメントが生成されます。
{ title: 'Star Trek' } { title: 'Star Trek: Nemesis' } { title: 'Star Trek: Insurrection' } { title: 'Star Trek: Generations' } { title: 'Star Trek: First Contact' } { title: 'Star Trek: The Motion Picture' } { title: 'Star Trek VI: The Undiscovered Country' } { title: 'Star Trek V: The Final Frontier' } { title: 'Star Trek IV: The Voyage Home' } { title: 'Star Trek III: The Search for Spock' } { title: 'Star Trek II: The Wrath of Khan' }
注意
クエリ操作により、一致するドキュメントを含むカーソルへの参照が返される場合があります。カーソルに格納されているデータを調べる方法については、「カーソルの基礎ページ」を参照してください。
関連性でソート
結果セットが目的の結果を反映したので、クエリプロジェクションで$meta演算子を使用してアクセスできるテキスト検索textScore
を使用して、結果を関連性で並べ替えることができます。
const query = { $text: { $search: "\"star trek\" -\"into darkness\"" } }; // sort returned documents by descending text relevance score const sort = { score: { $meta: "textScore" } }; // Include only the `title` and `score` fields in each returned document const projection = { _id: 0, title: 1, score: { $meta: "textScore" }, }; // find documents based on our query, sort, and projection const cursor = movies .find(query) .sort(sort) .project(projection);
この方法でクエリを実行すると、次の順序でそれぞれに掲げるドキュメントが返されます。一般に、テキストの関連性は、文字列で一致するタームが多くなるほど高くなり、文字列で一致しない部分が長くなるほど低下します。
{ title: 'Star Trek', score: 1.5 } { title: 'Star Trek: Generations', score: 1.3333333333333333 } { title: 'Star Trek: Insurrection', score: 1.3333333333333333 } { title: 'Star Trek: Nemesis', score: 1.3333333333333333 } { title: 'Star Trek: The Motion Picture', score: 1.25 } { title: 'Star Trek: First Contact', score: 1.25 } { title: 'Star Trek II: The Wrath of Khan', score: 1.2 } { title: 'Star Trek III: The Search for Spock', score: 1.2 } { title: 'Star Trek IV: The Voyage Home', score: 1.2 } { title: 'Star Trek V: The Final Frontier', score: 1.2 } { title: 'Star Trek VI: The Undiscovered Country', score: 1.2 }
$text 演算子とそのオプションの詳細については、マニュアル エントリを参照してください。