简体   繁体   中英

Linq: Best way to select parent rows order by count of children

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM