MongoDB Academy · レッスン

$metaによるテキストスコアでのソート

textScoreをプロジェクションしてソートし、関連性の高いドキュメントを結果の先頭に表示します。

レッスン 3/413 ステップ

「$metaによるテキストスコアでのソート」はCoddyKit上の無料MongoDB Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはMongoDB Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 MongoDB Academyコースには全4レッスンが含まれています。

textScore とは

$textクエリを実行すると、MongoDBは一致する各ドキュメントに対して、関連性スコアと呼ばれる値を計算します。このスコアは、ドキュメントが検索語にどの程度よく一致しているかを表します。検索語の出現回数が多いほど、重みの高いフィールドで一致するほど、また出現頻度の低いトークンで一致するほど、スコアは高くなります。デフォルトでは、結果はスコア順に並び替えられないため、明示的にソートを指定する必要があります。

$metaによるtextScoreのプロジェクション

結果に関連性スコアを含めるには、{ $meta: 'textScore' }を使用したプロジェクションフィールドを追加します。このフィールド名は自由に付けられますが、慣例的にはscoreとします。$meta式は、クエリ実行中に計算されたメタデータを読み取ります。このコンテキストで現在サポートされているメタデータ値はtextScoreだけです。

db.articles.find(
  { $text: { $search: 'mongodb performance' } },
  {
    title: 1,
    score: { $meta: 'textScore' }  // project the relevance score
  }
);

textScoreによるソート

関連性で結果をソートするには、{ score: { $meta: 'textScore' } }を.sort()に渡します。MongoDBでは、textScoreはデフォルトで降順(関連性が最も高いものから順)にソートされます。textScoreでソートする場合は、同じクエリでスコアフィールドもプロジェクションする必要があります。プロジェクションを省略してもMongoDBは正しくソートしますが、スコア値はクライアントに返されません。

db.articles
  .find(
    { $text: { $search: 'mongodb performance index' } },
    { title: 1, score: { $meta: 'textScore' } }
  )
  .sort({ score: { $meta: 'textScore' } });
// Results ordered: most relevant first

textScoreの計算方法

MongoDBのtextScoreは、TF-IDF(Term Frequency – Inverse Document Frequency、単語頻度–逆文書頻度)のロジックを変化させたものに基づいています。単語頻度:検索語が10回出現するドキュメントは、1回しか出現しないドキュメントより高いスコアになります。フィールドの重み:重み10のフィールドでの一致は、重み1のフィールドでの一致より10倍高いスコアになります。インデックスの密度:出現するドキュメントが少ない希少な単語は、非常に一般的な単語よりもスコアに大きく寄与します。

// Index with weights: title matches count more
db.articles.createIndex(
  { title: 'text', body: 'text' },
  { weights: { title: 10, body: 1 } }
);

// A document where 'mongodb' appears in the title
// scores 10x higher than one where it only appears in the body

集計パイプラインでの$meta

集計パイプラインでは、$addFieldsまたは$projectステージ内で{ $meta: 'textScore' }を使用してスコアを付加し、その後$sortに渡します。$textを使用する$matchステージは、パイプラインの最初に置く必要があります。これにより、他のステージでドキュメントストリームを変換する前に、MongoDBがスコアを計算できます。

db.articles.aggregate([
  { $match: { $text: { $search: 'nosql tutorial' } } },
  { $addFields: { score: { $meta: 'textScore' } } },
  { $sort: { score: -1 } },
  { $limit: 5 },
  { $project: { _id: 0, title: 1, score: 1 } }
]);

textScoreのソートと他のソートの組み合わせ

textScoreによるソートは、他のソートキーと組み合わせることができます。たとえば、まず関連性でソートし、同順位の場合は日付でソートできます。MongoDBはソートキーを左から右へ処理するため、関連性を優先するにはtextScoreを最初に指定します。追加のソートキーは、textScoreの値が同じドキュメント間の順序だけを決定します。

db.articles
  .find(
    { $text: { $search: 'mongodb' } },
    { title: 1, createdAt: 1, score: { $meta: 'textScore' } }
  )
  .sort({
    score: { $meta: 'textScore' },  // relevance first
    createdAt: -1                    // then newest
  });

最小スコアによるフィルタリング

関連性の高いドキュメントだけを返す場合は、$matchステージ内の$meta式を使用して、最小textScoreでフィルタリングできます(集計の場合)。これはテキスト検索の後に行います。直接的なfind()フィルターでは実行できません。まず集計パイプラインでスコアを計算し、その後でスコアを基準にフィルタリングする必要があります。

db.articles.aggregate([
  { $match: { $text: { $search: 'mongodb nosql' } } },
  { $addFields: { score: { $meta: 'textScore' } } },
  { $match: { score: { $gte: 1.5 } } },  // only high-relevance docs
  { $sort: { score: -1 } },
  { $project: { title: 1, score: 1 } }
]);

textScoreは絶対値を保証しない

textScoreの値は、1つのクエリ結果セット内で相対的なものであり、異なるクエリ間や異なるコレクションの状態間で絶対値として比較できるものではありません。コレクションにドキュメントを追加すると、単語頻度の計算が変わるため、今日のスコア2.5が明日には3.1になることがあります。textScoreは結果セット内のソートに使用し、保存する品質指標としては使用しないでください。

// Scores vary depending on collection content
// Useful for RANKING within a search result, not for thresholds
// Bad pattern:
const MIN_SCORE = 2.0;  // this threshold will drift as data grows

// Better pattern:
// Return the top N results sorted by score
db.articles
  .find({ $text: { $search: 'mongodb' } }, { score: { $meta: 'textScore' } })
  .sort({ score: { $meta: 'textScore' } })
  .limit(10);

テキスト検索結果のページネーション

標準的なskip()/limit()によるページネーションはテキスト検索でも使用できますが、深いオフセットでは通常どおりパフォーマンスの問題が発生します。結果は安定したフィールド順ではなく関連性順に並ぶため、テキスト検索結果でのキ​​ーセットページネーションは簡単ではありません。一般的な方法は、最初の数ページ(多くのユーザーがそこで閲覧をやめる範囲)ではオフセットページネーションを使用し、より深いページで大規模かつ一貫性の高いページネーションが必要になったらAtlas Searchを検討することです。

// Page 1 (skip 0)
db.articles
  .find({ $text: { $search: 'mongodb' } }, { score: { $meta: 'textScore' } })
  .sort({ score: { $meta: 'textScore' } })
  .skip(0).limit(10);

// Page 2 (skip 10) - gets slower on large result sets
db.articles
  .find({ $text: { $search: 'mongodb' } }, { score: { $meta: 'textScore' } })
  .sort({ score: { $meta: 'textScore' } })
  .skip(10).limit(10);

MongooseでのtextScore

Mongooseを使用する場合、スキーマパスの{ meta: 'textScore' }オプションを使用するか、scoreのメタプロジェクションを指定した.select()を使用してtextScoreにアクセスします。MongooseはMongoDBドライバーのAPIをラップしているため、基本的な概念は同じです。メタデータをプロジェクションおよびソートするためのMongoose構文を把握しておく必要があります。

// Mongoose text search with score projection
const results = await Article.find(
  { $text: { $search: 'mongodb nosql' } },
  { score: { $meta: 'textScore' } }  // same $meta syntax
).sort({ score: { $meta: 'textScore' } });

console.log(results.map(r => ({ title: r.title, score: r.score })));

textScoreでは不十分な場合

ネイティブテキストインデックスは単純な用途には適していますが、オートコンプリート、ファセット検索、同義語、カスタムランキング関数などの機能はありません。これらの機能が必要な場合は、MongoDB Atlas Search(Apache Lucene上に構築)が、BM25スコアリング、ブースト、関連性調整のためのexplain出力を備えた、より高機能な関連性スコアリングエンジンを提供します。

// Atlas Search provides richer scoring with the score option
// db.articles.aggregate([
//   { $search: {
//       text: { query: 'mongodb', path: 'title', score: { boost: { value: 3 } } },
//   } },
//   { $addFields: { score: { $meta: 'searchScore' } } },
//   { $sort: { score: -1 } }
// ]);
// --> Use Atlas Search when textScore is insufficient

クイックチェック

$metaを使用したテキストスコアによるソートについて、理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、textScoreは$textクエリの実行中に計算される、ドキュメントごとの関連性スコアであること、{ $meta: 'textScore' }によってこのスコアをプロジェクションおよびソートできること、そしてフィールドの重みと単語頻度によってスコアの大きさが決まることを学びました。次は、テキストインデックスの制限と、Atlas Searchを選ぶべき場合について説明します。

無料で開始

AI チューターと学ぶ JavaScript — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
30
レッスン
120

よくある質問

「$metaによるテキストスコアでのソート」レッスンは無料ですか?

はい。「$metaによるテキストスコアでのソート」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、MongoDB Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 MongoDB Academyコースには全4レッスンが含まれています。

「$metaによるテキストスコアでのソート」で何を学びますか?

textScoreをプロジェクションしてソートし、関連性の高いドキュメントを結果の先頭に表示します。 ブラウザで直接実行するハンズオンコードでMongoDB Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

MongoDB Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのMongoDB Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「$metaによるテキストスコアでのソート」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このMongoDB Academyレッスンでコードを書いて実行できますか?

はい。すべてのMongoDB Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 文字列フィールドへのテキストインデックスの作成
  2. フレーズと否定を使った$textクエリの実行
  3. $metaによるテキストスコアでのソート
  4. テキストインデックスの制限とAtlas Searchを使う場面
← MongoDB Academyに戻る