問題は次の問題です。
リスト内のタグを含むドキュメントを、一致の総数順に並べて取得します
しかし、Aggregation Framework を使えばそれが可能だと彼らは言いますが、可能でしょうか?
はい、Aggregation Framework を使用して可能です。
仮定
tags
属性はセットです (繰り返し要素はありません)クエリ
このアプローチでは、結果をアンワインドし、アンワインドされた結果で一致述語を再評価する必要があるため、非常に非効率的です。
db.test_col.aggregate(
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$unwind: "$tags"},
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$group: {
_id:{"_id":1},
matches:{$sum:1}
}},
{$sort:{matches:-1}}
);
予想された結果
{
"result" : [
{
"_id" : {
"_id" : ObjectId("5051f1786a64bd2c54918b26")
},
"matches" : 3
},
{
"_id" : {
"_id" : ObjectId("5051f1726a64bd2c54918b24")
},
"matches" : 2
},
{
"_id" : {
"_id" : ObjectId("5051f1756a64bd2c54918b25")
},
"matches" : 1
}
],
"ok" : 1
}
$sizeと$setIntersectionを使用すると、メモリの増加を引き起こすことなく、これを効率的に解決できます。
tagList = ['shirt', 'cotton', 'black']
db.test_col.aggregate(
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$project:
{"title":1,"tags":1},
{$order:
{"$size":
{"$setIntersection": [ tagList, "$tags" ]}},
{$sort:{order:-1}}
);
最初に、少なくとも 1 つの要素が一致するドキュメントを照合します。
次に、必要なキー/列を新しい順序キー/列と共に射影します。順序は、'tags in db' と 'tags from query' の間で交差する要素の数を取得することによって生成されます。
次に、降順で単純なソートを行います。これは私にとってはうまくいきました。同様の質問がここで回答されました