私は2つのコレクションを持っています
投稿:
{
"_Id": "1",
"_PostTypeId": "1",
"_AcceptedAnswerId": "192",
"_CreationDate": "2012-02-08T20:02:48.790",
"_Score": "10",
...
"_OwnerUserId": "6",
...
},
...
およびユーザー:
{
"_Id": "1",
"_Reputation": "101",
"_CreationDate": "2012-02-08T19:45:13.447",
"_DisplayName": "Geoff Dalgas",
...
"_AccountId": "2"
},
...
5~15 件の投稿をしたユーザーを見つけたいとします。クエリは次のようになります。
db.posts.aggregate([
{
$lookup: {
from: "users",
localField: "_OwnerUserId",
foreignField: "_AccountId",
as: "X"
}
},
{
$group: {
_id: "$X._AccountId",
posts: { $sum: 1 }
}
},
{
$match : {posts: {$gte: 5, $lte: 15}}
},
{
$sort: {posts: -1 }
},
{
$project : {posts: 1}
}
])
動作がひどく遅いです。6,000 人のユーザーと 10,000 件の投稿に対して、応答を得るのに 40 秒以上かかりましたが、リレーショナル データベースでは、ほんの一瞬で応答が得られます。どこに問題があるのでしょうか? 私は mongodb を使い始めたばかりで、このクエリを間違えた可能性があります。
ベストアンサー1
からhttps://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
foreignField は、from コレクション内のドキュメントのフィールドを指定します。$lookupはforeignFieldで等価性マッチを実行します入力ドキュメントの localField に追加します。from コレクション内のドキュメントに foreignField が含まれていない場合、$lookup は一致のために値を null として扱います。
これは他のクエリと同じように実行されます。
_AccountId フィールドにインデックスがない場合、10,000 件の投稿それぞれに対して完全なテーブルスキャン クエリが実行されます。時間の大部分は、このテーブルスキャンに費やされます。
db.users.ensureIndex("_AccountId", 1)
プロセスが高速化され、10,000 回のテーブル スキャンではなく 10,000 回のインデックス ヒットが実行されます。