ユーザーが独自のブログを作成できるブログ プラットフォームに mongodb を使用しています。すべてのブログのすべてのエントリがエントリ コレクションに含まれています。エントリのドキュメントは次のようになります。
{
'blog_id':xxx,
'timestamp':xxx,
'title':xxx,
'content':xxx
}
質問が示すように、各ブログの最後の 3 つのエントリを選択する方法はありますか?
ユーザーが独自のブログを作成できるブログ プラットフォームに mongodb を使用しています。すべてのブログのすべてのエントリがエントリ コレクションに含まれています。エントリのドキュメントは次のようになります。
{
'blog_id':xxx,
'timestamp':xxx,
'title':xxx,
'content':xxx
}
質問が示すように、各ブログの最後の 3 つのエントリを選択する方法はありますか?
最初にコレクション内のドキュメントをblog_id
およびtimestamp
フィールドで並べ替え、次に元のドキュメントの配列を降順で作成する初期グループを実行する必要があります。その後、配列をドキュメントでスライスして、最初の 3 つの要素を返すことができます。
この例では、直感に従うことができます。
db.entries.aggregate([
{ '$sort': { 'blog_id': 1, 'timestamp': -1 } },
{
'$group': {
'_id': '$blog_id',
'docs': { '$push': '$$ROOT' },
}
},
{
'$project': {
'top_three': {
'$slice': ['$docs', 3]
}
}
}
])
別の質問からのdrcostaによるmap reduceを使用したこの回答は、うまくいきました
mongoでは、map reduceを使用してグループを最新順に並べ替えるにはどうすればよいですか
mapper = function () {
emit(this.category, {top:[this.score]});
}
reducer = function (key, values) {
var scores = [];
values.forEach(
function (obj) {
obj.top.forEach(
function (score) {
scores[scores.length] = score;
});
});
scores.sort();
scores.reverse();
return {top:scores.slice(0, 3)};
}
function find_top_scores(categories) {
var query = [];
db.top_foos.find({_id:{$in:categories}}).forEach(
function (topscores) {
query[query.length] = {
category:topscores._id,
score:{$in:topscores.value.top}
};
});
return db.foo.find({$or:query});
2つのことで生活できる場合、基本的なmongoでこれを行う唯一の方法:
その場合は、次のようにします。
新しいイントロを作成したら、通常の挿入を行ってから、この更新を実行して、すべての投稿 (このブログに挿入したものを含む) の年齢を上げます。
db.entries.update({blog_id: BLOG_ID}, {age:{$inc:1}}, false, true)
クエリを実行するときは、ブログごとに最新の 3 つのエントリを返す次のクエリを使用します。
db.entries.find({age:{$lte:3}, timestamp:{$gte:STARTOFMONTH, $lt:ENDOFMONTH}}).sort({blog_id:1, age:1})
このソリューションは、実際には同時実行に対して安全であることに注意してください (年齢が重複するエントリはありません)。
グループ (集計) で可能ですが、これによりテーブル全体のスキャンが作成されます。
本当に正確に 3 つ必要ですか、それとも制限を設定できますか? 例: 先週/月から最大 3 つの投稿?