我想根据喜欢
和日期
显示数据库中的帖子列表,想想基本的“趋势”项目页面。
我想使用像 score = likes/daysSinceCreation
这样的公式,然后根据这个分数获取前 10 个帖子。
如何使用 mongoDB/Mongoose 添加排序功能?
Posts.find().sort(???).limit(10).then(posts => console.log(posts));
目前我可以获得上周的热门帖子(查找创建日期是否大于上周并按分数排序),但是如何在不从数据库获取所有项目的情况下实现更复杂的排序功能?
例如: 今天是星期五ID CREATION_DAY LIKES
1 Monday 4 // score is 5/5 = 0
2 Tuesday 10 // score is 10/4 = 2
3 Wednesday 3 // score is 3/3 = 1
4 Thursday 20 // score is 20/2 = 10
5 Friday 5 // score is 5/1 = 5
ID 的排序列表为:[4 (Th), 5 (Fr), 2 (Tu), 3 (We), 1(Mo)]
最佳答案
这将在“trendingposts”表中创建一个新文档:
const fiveDaysAgo = new Date(Date.now() - (5 * 24 * 60 * 60 * 1000));
const oid = new ObjectId();
const now = new Date();
Posts.aggregate([
{
$match: {
createdAt: {
$gte: fiveDaysAgo
},
score: {
$gt: 0
}
}
},
{
$project: {
_id: true,
createdAt: true,
updatedAt: true,
title: true,
description: true,
score: true,
trendScore: {
$divide: [ "$score", {$subtract: [new Date(), "$createdAt"]} ]
}
}
},
{
$sort: {
trendScore: -1
}
},
{
$limit: 10
},
{
$group: {
_id: { $min: oid },
evaluatedAt: { $min: now },
posts: { $push: "$$ROOT"}
}
},
{
$out: "trendingposts"
}
])
.then(...)
需要注意的几点:
如果使用 Mongo 3.4+,$project 阶段也可以写成:
{ $addFields: { trendScore: { $divide: [ "$score", {$subtract: [new Date(), "$createdAt"]} ] } } },
{ $min: now }
只是一种获取每个文档上now
的最小值的 hack,即使它对于所有文档来说都是相同的值他们。"$$ROOT"
是整个当前文档。这意味着您的最终结果将是具有以下形式的单个对象:{ "_id" : ObjectId("5a0a2fe912a325eb331f2759"), "evaluatedAt" : ISODate("2017-11-13T23:51:56.051Z"), "posts" : [/*10 `post` documents, sorted by trendScore */] }
然后您可以使用以下方式查询:
TrendingPosts.findOne({})
.sort({_id: -1})
.then(trendingPost => console.log(trendingPost));
如果您的描述/标题经常更改,您可以只推送 ID 并将其用于 $in
查询,而不是 $push
整个文档在您的帖子上,以保证最新数据。
关于javascript - Mongoose 查询 "hot"帖子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47274340/