I have got a table for Comments like following:
Comment{
ID,
Text,
ParentID
}
I am using following query to select the popular comments with paging based on number of replies.
var comments = db.Comments
.OrderByDescending(c => db.Comments.Count(r => r.ParentID == c.ID)).Skip(skip).Take(recordsPerPage).ToList();
Please let me know the best way of handling this situation when we have thousands of comments?
I would consider adding an extra column to Comment
that stores the replies count.Then instead making a nested query you can easily order your Comments
by replies count.
var comments = db.Comments.Skip(skip).Take(recordsPerPage)
.OrderByDescending(c => c.ReplyCount)
.ToList();
Unless you are prepared to pre-calculate this in the database then you have the problem that you need to either do nested queries or to do a single full fetch an then do everything in memory. The latter is my choice until it is proven to be too slow.
Here's how I'd initially do it.
First, pre-fetch:
var allComments = Comments.ToArray();
Then create a function that will quickly return the count of comments:
var childrenLookup = allComments.ToLookup(x => x.ParentID);
var parentMap = allComments.ToDictionary(x => x.ID, x => x.ParentID);
Func<int, int> getCommentsCount = n =>
{
var r = 0;
if (parentMap.ContainsKey(n))
{
r = childrenLookup[parentMap[n]].Count();
}
return r;
};
Now it is almost trivial to return the results:
var comments = allComments
.OrderByDescending(c => getCommentsCount(c.ID))
.Skip(skip)
.Take(recordsPerPage)
.ToList();
(And, yes, your ordering is in the wrong order to you skip and take for paging.)
If you can't do this in memory then go with the pre-calculate approach.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.