按数组大小对结果排序
Sort results by array size
我有一个名为article的集合,我需要根据它包含的数组的大小对返回的对象进行排序。最好的方法是什么?我想到的一种方法是检索整个对象列表并在JS中手动排序。但是我每次返回10篇文章,所以每次调用这个API时,它都必须做不必要的排序数组的工作。
Article.find({})
.limit(10)
.skip(req.params.page*10)
//Something like using $project to make a new variable called votecount that counts objects in a given array.
.sort({votecount:-1})
.exec(function(err,arts){
articleObj.articles = arts;
if (arts.length<10){
articleObj.reachedEnd = true;
}
res.json(articleObj);
});
我需要清点选票。这是一个示例对象:
{
"_id" : ObjectId("55f50cfddcf1ad6931fb8dd4"),
"timestamp" : "2015-09-13T00:58:57-5:00",
"url" : "http://www.nytimes.com/2015/09/13/sports/floyd-mayweather-finishes-bout-and-maybe-his-career-with-lopsided-win-over-andre-berto.html",
"abstract" : "Mayweather’s victory by unanimous decision gave him a record of 49-0, the same as the legendary heavyweight Rocky Marciano.",
"title" : "Mayweather Wins Easily in What He Calls Last Bout",
"section" : "Sports",
"comments" : [ ],
"votes" : {
"up" : [
ObjectId("55e5e16934d355d61c471e48")
],
"down" : [ ]
},
"image" : {
"caption" : "Floyd Mayweather Jr. after learning he defeated Andre Berto in a unanimous decision.",
"url" : "http://static01.nyt.com/images/2015/09/14/sports/13fight/13fight-mediumThreeByTwo210.jpg"
},
"__v" : 0
}
您需要.aggregate()
方法,因为所有"sort"参数必须是文档中存在的字段,这样您可以将数组的$size
"投影"到文档中进行排序:
Article.aggregate(
[
{ "$project": {
"timestamp": 1,
"url": 1,
"abstract": 1,
"title": 1,
"section": 1,
"comments": 1,
"votes": 1,
"image": 1,
"voteCount": {
"$subtract": [
{ "$size": "$votes.up" },
{ "$size": "$votes.down" }
]
}
}},
{ "$sort": { "voteCount": -1 } },
{ "$skip": req.params.page*10 },
{ "$limit": 10 },
],
function(err,results) {
// results here
}
);
当然,这是有代价的,因为你需要在每次迭代中计算大小。因此,更好的做法是在每次更新操作时保持文档中的"投票计数",并且更好地使用批量操作来适应所有情况:
var bulk = Atricle.collection.intializeOrderedBulkOp();
// Swap out a downvote where present
bulk.find({
"_id": id,
"votes.up": { "$ne": userId },
"votes.down": userId
}).updateOne({
"$push": { "votes.up": userId },
"$pull": { "votes.down": userId }
"$inc": { "voteCount": 2 }
});
// Add an upvote where not present
bulk.find({
"_id": id,
"votes.up": { "$ne": userId },
"votes.down": { "$ne": userId }
}).updateOne({
"$push": { "votes.up": userId },
"$inc": { "voteCount": 1 }
});
bulk.execute(function(err,response) {
// maybe do something here
});
当然,"downvote"是这个过程的相反。
这里的要点是,当每次投票被处理时,"计数"或"分数"同时保持更新。这允许正常的查询和排序,而不需要在每次访问数据时进行计算,因为它已经完成了。
后一种情况是处理这个问题的最有效的方法
相关文章:
- Javascript表排序工作得很好,但对所有索引进行迭代会得到不同的结果
- 如何对javascript表进行排序(升序或降序),该表是某些SQL操作表的结果
- 如何在AngularJS中根据子结果集排序结果
- 重新排序angularjs ngRepeat与后续数据结果
- 对indexedDB查询的结果进行排序
- 如何对select2自动完成结果进行排序,只显示以第一个字母开头的项目
- 使用 Greasemonkey 修改 Craigslist 的默认搜索结果排序
- 根据所选排序动态更改结果
- 按活动排序,但不在结果中显示活动
- 按距离对搜索结果进行排序
- 使用 AJAX 回调更新挖空可观察数组会生成随机排序的结果
- JS AJAX 提前键入结果排序/竞争条件
- Javascript JSON 结果排序
- 将对象属性设置为排序结果而不进行排序
- 检索两个列表,对值进行排序和比较,然后显示所有结果
- 随后的多维数组排序会产生意外的结果
- javascript排序和排序等于结果.怎样
- 按HTML表列对查询结果排序
- 按数组大小对结果排序
- 通过JavaScript奇数结果排序JSON对象