次の構造を持つ「投稿」と呼ばれるコレクションがあると仮定します(実際には、それはより複雑なコレクションであり、投稿は単純すぎます)。
> db.posts.find()
{ "_id" : ObjectId("50ad8d451d41c8fc58000003"), "title" : "Lorem ipsum", "author" :
"John Doe", "content" : "This is the content", "tags" : [ "SOME", "RANDOM", "TAGS" ] }
このコレクションは数十万、おそらく数百万に及ぶと予想しています。タグで投稿をクエリし、タグで結果をグループ化して、ページ分けされた結果を表示する必要があります。これが集約フレームワークの出番です。私は、aggregate()メソッドを使用してコレクションを照会する予定です。
db.posts.aggregate([
{ "$unwind" : "$tags" },
{ "$group" : {
_id: { tag: "$tags" },
count: { $sum: 1 }
} }
]);
問題は、ページネーションを作成するには、出力配列の長さを知る必要があるということです。私はそれをするためにあなたができることを知っています:
db.posts.aggregate([
{ "$unwind" : "$tags" },
{ "$group" : {
_id: { tag: "$tags" },
count: { $sum: 1 }
} }
{ "$group" : {
_id: null,
total: { $sum: 1 }
} }
]);
しかし、それは前のパイプライン(最初のグループ)からの出力を破棄します。各パイプラインの出力を保持しながら、2つの操作を組み合わせる方法はありますか?集計操作全体の出力を一部の言語で配列にキャストして内容をカウントできることは知っていますが、パイプラインの出力が16Mbの制限を超える可能性があります。また、カウントを取得するためだけに同じクエリを実行するのは無駄のようです。
では、ドキュメントの結果とカウントを同時に取得することは可能ですか?どんな助けでもありがたいです。
$project
tag
およびcount
をtmp
に保存するには$Push
またはaddToSet
は、tmp
をdata
リストに保存します。コード:
db.test.aggregate(
{$unwind: '$tags'},
{$group:{_id: '$tags', count:{$sum:1}}},
{$project:{tmp:{tag:'$_id', count:'$count'}}},
{$group:{_id:null, total:{$sum:1}, data:{$addToSet:'$tmp'}}}
)
出力:
{
"result" : [
{
"_id" : null,
"total" : 5,
"data" : [
{
"tag" : "SOME",
"count" : 1
},
{
"tag" : "RANDOM",
"count" : 2
},
{
"tag" : "TAGS1",
"count" : 1
},
{
"tag" : "TAGS",
"count" : 1
},
{
"tag" : "SOME1",
"count" : 1
}
]
}
],
"ok" : 1
}
すべてのタグをカウントする以外に、このための集約フレームワークが必要かどうかはわかりません。例:
db.posts.aggregate(
{ "unwind" : "$tags" },
{ "group" : {
_id: { tag: "$tags" },
count: { $sum: 1 }
} }
);
タグごとにページ番号を付けるには、次のように通常のクエリ構文を使用できます。
db.posts.find({tags: "RANDOM"}).skip(10).limit(10)