MongoDB
 Computer >> コンピューター >  >> プログラミング >> MongoDB

MongoDBで類似した配列を持つドキュメントを検索し、類似度でソートする方法

はじめに

MongoDBでは、配列フィールドを持つ複数のドキュメントの中から、基準となる配列とどれだけ一致しているか(類似度)に基づいて検索し、結果をランキングしたいケースがあります。本記事では、集計パイプライン(aggregate)を活用して、類似した配列を持つドキュメントを検索し、一致率の高い順にソートする方法を具体例とともに解説します。

サンプルコレクションの作成

まず、配列フィールドを含むドキュメントを持つコレクションを作成しましょう。

> db.demo123.insertOne({"ListOfSubject":['MySQL', 'MongoDB', 'Java']});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e2f24ac140daf4c2a3544b8")
}
> db.demo123.insertOne({"ListOfSubject":['Python', 'MongoDB', 'C']});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e2f24cd140daf4c2a3544b9")
}
> db.demo123.insertOne({"ListOfSubject":['MySQL', 'MongoDB', 'C++']});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e2f24ce140daf4c2a3544ba")
}

find()メソッドを使用して、コレクション内のすべてのドキュメントを確認します。

> db.demo123.find();

実行すると、次のような出力が得られます。

{ "_id" : ObjectId("5e2f24ac140daf4c2a3544b8"), "ListOfSubject" : [ "MySQL", "MongoDB", "Java" ] }
{ "_id" : ObjectId("5e2f24cd140daf4c2a3544b9"), "ListOfSubject" : [ "Python", "MongoDB", "C" ] }
{ "_id" : ObjectId("5e2f24ce140daf4c2a3544ba"), "ListOfSubject" : [ "MySQL", "MongoDB", "C++" ] }

類似した配列を持つドキュメントを検索して並べ替えるクエリ

以下が、基準となる配列と共通する要素を持つドキュメントを検索し、一致率(類似度)で並べ替えるためのクエリです。

> var subjects = ['MySQL', 'MongoDB', 'Java'];
> db.demo123.aggregate([
...    {$unwind: "$ListOfSubject"},
...    {$match: {ListOfSubject:{ $in:subjects}}},
...    {$group: {_id: "$_id", number: {$sum: 1}}},
...    {$project: {_id: 1, number: 1, percentage: {$divide: ["$number",subjects.length]}}},
...    {$sort: {percentage: -1}}
... ]);

実行すると、次のような出力が得られます。

{ "_id" : ObjectId("5e2f24ac140daf4c2a3544b8"), "number" : 3, "percentage" : 1 }
{ "_id" : ObjectId("5e2f24ce140daf4c2a3544ba"), "number" : 2, "percentage" : 0.6666666666666666 }
{ "_id" : ObjectId("5e2f24cd140daf4c2a3544b9"), "number" : 1, "percentage" : 0.3333333333333333 }

この結果から、基準の配列「['MySQL', 'MongoDB', 'Java']」と完全に一致する最初のドキュメントが一致率100%(1)、3つ中2つが一致する3番目のドキュメントが約66%、1つのみ一致する2番目のドキュメントが約33%として、類似度の降順に並んでいることがわかります。

クエリの仕組み

各ステージの役割は以下の通りです。

  • $unwind: 配列フィールド「ListOfSubject」を展開し、要素ごとに個別のドキュメントへ分割します。
  • $match: 基準となるsubjects配列に含まれる要素だけを抽出します。
  • $group: ドキュメントの_idごとにグループ化し、$sumで一致した要素数をカウントします。
  • $project: 一致数を基準配列の長さで除算し、一致率(percentage)を計算します。
  • $sort: 一致率の降順で結果を並べ替えます。

まとめ

aggregateフレームワークの$unwind、$match、$group、$project、$sortを組み合わせることで、配列同士の類似度に基づいたドキュメントの検索とランキングが簡単に実現できます。タグのマッチングや推薦機能など、実用的なユースケースにも応用できるテクニックなので、ぜひ活用してください。

  1. MongoDBでforループを使用して値をプッシュ(挿入)する方法

    MongoDBでforループを使用して値をプッシュ(挿入)する方法MongoDBで値を繰り返しコレクションへ挿入(プッシュ)したい場合、save()メソッドとforループを組み合わせることで簡単に実現できます。ここでは、実際のコード例を交えながら手順を解説します。1. forループでドキュメントを作成するまず、forループを使ってコレクションにドキュメントを作成します。以下の例では、ループを6回まわして同じ内容のドキュメントを保存しています。> for(var v=1; v<7; v++) {... db.demo739.save({Name:Chris,SubjectName:M

  2. MongoDBでオブジェクト配列内の特定のネストされたドキュメントをクエリする方法

    MongoDBでオブジェクトの配列からネストされたドキュメントを抽出する オブジェクトの配列に格納されたネストされたドキュメントを条件付きで検索したい場合、find()メソッドに$elemMatch演算子を組み合わせることで、指定した条件に一致する要素だけを取り出すことができます。 ここでは、「StudentAge」フィールドを持つ学生情報だけを配列から抽出する例を見ていきましょう。 1. サンプルコレクションの作成 まず、ドキュメントを挿入してコレクションを作成します。このコレクションには、学生情報がオブジェクトの配列として格納されています。 > db.demo763.insertO