优化社交APP「可能认识的人」模块:获取非好友的更优方案?
优化「可能认识的人」查询代码
我正在开发一款类似Facebook的社交APP,支持添加好友功能,想做一个「可能认识的人」板块,展示除好友外的所有应用用户。
现有模型定义
ApplicationUser 模型
public class ApplicationUser : IdentityUser { public string Fullname { get; set; } public DateOnly BirthDate { get; set; } public string? ProfilePicUrl { get; set; } public string Bio { get; set; } public ICollection<User_Friend> Users { get; set; } public ICollection<User_Friend> Friends { get; set; } }
User_Friend 关联模型
public class User_Friend { public int Id { get; set; } public string UserId { get; set; } public ApplicationUser User { get; set; } public string FriendId { get; set; } public ApplicationUser Friend { get; set; } public DateTime FriendsSince { get; set; } }
当前实现(功能正常但冗余)
public IActionResult Index() { var claim = (ClaimsIdentity)User.Identity; var user = claim.FindFirst(ClaimTypes.NameIdentifier); //everyone ids except me List<string> AllIds = _context.applicationUsers .Where(u => u.Id != user.Value) .Select(x => x.Id).ToList(); // friends ids List<string> friendsIds = _context.user_Friends .Where(u => u.UserId == user.Value) .Select(x => x.FriendId) .ToList(); // non-friends ids List<string> nonFriendsIds = AllIds.Except(friendsIds).ToList(); List<ApplicationUser> nonFriends = new List<ApplicationUser>(); if (user != null) { foreach (var x in nonFriendsIds) { nonFriends.Add(_context.applicationUsers.FirstOrDefault(u => u.Id == x)); } } return View(nonFriends); }
优化方案
方案一:单查询直接过滤
通过合并查询逻辑,减少数据库交互次数,同时简化代码:
public IActionResult Index() { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (userId == null) { return View(new List<ApplicationUser>()); } var nonFriends = _context.applicationUsers .Where(u => u.Id != userId) .Where(u => !_context.user_Friends.Any(uf => uf.UserId == userId && uf.FriendId == u.Id)) .ToList(); return View(nonFriends); }
方案二:左连接实现
使用Linq左连接语法,逻辑更直观:
public IActionResult Index() { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (userId == null) { return View(new List<ApplicationUser>()); } var nonFriendsQuery = from user in _context.applicationUsers join friendLink in _context.user_Friends on user.Id equals friendLink.FriendId into linkedFriends from link in linkedFriends.DefaultIfEmpty() where user.Id != userId && link == null select user; return View(nonFriendsQuery.ToList()); }
优化点总结
- 用
User.FindFirstValue简化当前用户ID的获取,无需强制类型转换 - 将多次数据库查询合并为一次,降低IO开销
- 避免先查ID再循环查询用户的冗余操作,直接返回目标用户集合
- 提前处理未登录场景,返回空列表保证代码健壮性
内容的提问来源于stack exchange,提问作者Sulabee
相关产品推荐
相关产品推荐

