Skip to content

Commit e57d31a

Browse files
authored
Merge pull request #21 from TheInfinityNet/20-fix-get-suggestion
fix get mutual friend count
2 parents 9ad200e + 6b812ae commit e57d31a

File tree

11 files changed

+206
-38
lines changed

11 files changed

+206
-38
lines changed

Application/GrpcClients/CommonRelationshipClient.cs

+19-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public async Task<IList<string>> GetAllBlockerIds(string profileId)
218218
throw new BaseException(BaseError.RELATIONSHIP_NOT_FOUND, StatusCodes.Status404NotFound);
219219
}
220220
}
221-
221+
222222
public async Task<IList<string>> GetAllBlockeeIds(string profileId)
223223
{
224224
try
@@ -237,6 +237,24 @@ public async Task<IList<string>> GetAllBlockeeIds(string profileId)
237237
throw new BaseException(BaseError.RELATIONSHIP_NOT_FOUND, StatusCodes.Status404NotFound);
238238
}
239239
}
240+
public async Task<IList<ProfileIdWithMutualCount>> GetFriendsOfMutualFriends(string profileId)
241+
{
242+
try
243+
{
244+
logger.LogInformation("Starting get mutual friend list");
245+
var response = await client.getFriendsOfMutualFriendsAsync(new ProfileRequest
246+
{
247+
Id = profileId
248+
});
249+
// Call the gRPC server to introspect the token
250+
return response.ProfileIdsWithMutualCounts;
251+
}
252+
catch (Exception e)
253+
{
254+
logger.LogError(e.Message);
255+
throw new BaseException(BaseError.RELATIONSHIP_NOT_FOUND, StatusCodes.Status404NotFound);
256+
}
257+
}
240258
public async Task<IList<ProfileIdWithMutualCount>> CountMutualFriends(string profileId, IList<string> profileIds)
241259
{
242260
try

Application/Protos/relationship.proto

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ service RelationshipService {
7070

7171
rpc countMutualFriends(MutualFriendCountRequest) returns (MutualFriendCountResponse) {}
7272

73+
rpc getFriendsOfMutualFriends(ProfileRequest) returns (MutualFriendCountResponse) {}
74+
7375
rpc getAllPendingRequestIds(ProfileRequest) returns (ProfileIdsResponse) {}
7476

7577
rpc getAllRequestIds(ProfileRequest) returns (ProfileIdsResponse) {}

Profile.Application/IServices/IUserProfileService.cs

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public interface IUserProfileService
1717

1818
public Task<UserProfile> Update(UserProfile userProfile);
1919

20+
public Task<CursorPagedResult<UserProfile>> SearchFriend(string keyword, string profileId, string cursor, int limit);
21+
2022
public Task<CursorPagedResult<UserProfile>> GetFriendSuggestions(string profileId, string cursor, int limit);
2123

2224
public Task<CursorPagedResult<UserProfile>> GetFriendRequests(string profileId, string cursor, int limit);

Profile.Application/Services/UserProfileService.cs

+30-7
Original file line numberDiff line numberDiff line change
@@ -166,26 +166,49 @@ public async Task<CursorPagedResult<UserProfile>> GetFriendSentRequests(string p
166166

167167
public async Task<CursorPagedResult<UserProfile>> GetFriendSuggestions(string profileId, string cursor, int limit)
168168
{
169-
IList<string> followeeIds = await relationshipClient.GetAllFolloweeIds(profileId);
170-
IList<string> friendIds = await relationshipClient.GetAllFriendIds(profileId);
169+
//IList<string> followeeIds = await relationshipClient.GetAllFolloweeIds(profileId);
170+
//IList<string> friendIds = await relationshipClient.GetAllFriendIds(profileId);
171+
var friendsOfMutualFriends = await relationshipClient.GetFriendsOfMutualFriends(profileId);
171172
IList<string> pendingRequests = await relationshipClient.GetAllPendingRequestIds(profileId);
172173
IList<string> blockerIds = await relationshipClient.GetAllBlockerIds(profileId.ToString());
173174
IList<string> blockeeIds = await relationshipClient.GetAllBlockeeIds(profileId.ToString());
175+
var mutualFriendIds = friendsOfMutualFriends
176+
.Select(item => item.ProfileId)
177+
.ToList();
174178

175179
var specification = new SpecificationWithCursor<UserProfile>
176180
{
177181
Criteria = userProfile =>
178-
!userProfile.Id.Equals(Guid.Parse(profileId))
179-
&& !friendIds.Contains(userProfile.Id.ToString())
180-
&& !pendingRequests.Contains(userProfile.Id.ToString())
181-
&& !blockerIds.Concat(blockeeIds).Contains(userProfile.Id.ToString())
182-
&& !blockerIds.Concat(blockeeIds).Contains(userProfile.Id.ToString()),
182+
mutualFriendIds.Contains(userProfile.Id.ToString())
183+
& !userProfile.Id.Equals(Guid.Parse(profileId))
184+
//&& !friendIds.Contains(userProfile.Id.ToString())
185+
& !pendingRequests.Contains(userProfile.Id.ToString())
186+
& !blockerIds.Concat(blockeeIds).Contains(userProfile.Id.ToString())
187+
& !blockerIds.Concat(blockeeIds).Contains(userProfile.Id.ToString()),
183188
Cursor = cursor,
184189
Limit = limit
185190
};
186191
return await userProfileRepository.GetPagedAsync(specification);
187192
}
193+
public async Task<CursorPagedResult<UserProfile>> SearchFriend(string keywords, string profileId, string cursor, int limit)
194+
{
188195

196+
IList<string> blockerIds = await relationshipClient.GetAllBlockerIds(profileId.ToString());
197+
IList<string> blockeeIds = await relationshipClient.GetAllBlockeeIds(profileId.ToString());
198+
199+
var specification = new SpecificationWithCursor<UserProfile>
200+
{
201+
Criteria = userProfile =>
202+
(string.IsNullOrEmpty(keywords) ||
203+
userProfile.FirstName.Contains(keywords, StringComparison.CurrentCultureIgnoreCase) ||
204+
userProfile.LastName.Contains(keywords, StringComparison.CurrentCultureIgnoreCase) ||
205+
userProfile.Username.Contains(keywords, StringComparison.CurrentCultureIgnoreCase))
206+
&!blockerIds.Concat(blockeeIds).Contains(userProfile.Id.ToString()),
207+
Cursor = cursor,
208+
Limit = limit
209+
};
210+
return await userProfileRepository.GetPagedAsync(specification);
211+
}
189212
public async Task<UserProfile> GetByAccountId(string id)
190213
=> await userProfileRepository.GetByAccountIdAsync(Guid.Parse(id));
191214

Profile.Presentation/Controllers/FriendController.cs

+54
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,60 @@ public async Task<IActionResult> GetFriendSuggestions([FromQuery] string nextCur
9191
});
9292
}
9393

94+
[EndpointDescription("Retrieve friend suggestions")]
95+
[ProducesResponseType(typeof(CursorPagedResult<FriendshipResponse>), StatusCodes.Status200OK)]
96+
[Authorize]
97+
[HttpGet("search")]
98+
public async Task<IActionResult> SearchFriends([FromQuery] string nextCursor, [FromQuery] int limit = 10)
99+
{
100+
string currentProfileId = GetCurrentProfileId != null ? GetCurrentProfileId().ToString()
101+
: throw new BaseException(BaseError.PROFILE_NOT_FOUND, StatusCodes.Status404NotFound);
102+
103+
var suggestions = await userProfileService.GetFriendSuggestions(currentProfileId, nextCursor, limit);
104+
105+
var photoMetadataIds = suggestions.Items
106+
.Where(profile => profile.AvatarId != null)
107+
.Select(profile => profile.AvatarId)
108+
.Distinct();
109+
110+
var photoMetadataTasks = photoMetadataIds.Select(async id =>
111+
{
112+
var metadata = await fileClient.GetPhotoMetadata(id.ToString());
113+
return new { Id = id, Metadata = metadata ??= new PhotoMetadataResponse { Id = id.Value } };
114+
});
115+
var photoMetadataDict = (await Task.WhenAll(photoMetadataTasks)).ToDictionary(x => x.Id, x => x.Metadata);
116+
117+
var resultHasCount = await relationshipClient
118+
.CountMutualFriends(currentProfileId, suggestions.Items.Select(f => f.Id.ToString()).ToList());
119+
120+
var resultHasCountDict = resultHasCount.ToDictionary(p => p.ProfileId);
121+
122+
IList<FriendshipResponse> result = [];
123+
foreach (var item in suggestions.Items)
124+
{
125+
var userProfile = mapper.Map<UserProfileResponse>(item);
126+
if (userProfile.Avatar != null)
127+
{
128+
if (photoMetadataDict.TryGetValue(item.AvatarId, out var avatar))
129+
{
130+
userProfile.Avatar = avatar;
131+
}
132+
}
133+
134+
var itemResponse = mapper.Map<FriendshipResponse>(userProfile);
135+
itemResponse.Status = "NotConnected";
136+
if (resultHasCountDict.TryGetValue(item.Id.ToString(), out var rs))
137+
if (rs.Count > 0) itemResponse.MutualFriendsCount = rs.Count;
138+
139+
result.Add(itemResponse);
140+
}
141+
142+
return Ok(new CursorPagedResult<FriendshipResponse>()
143+
{
144+
Items = result,
145+
NextCursor = suggestions.NextCursor
146+
});
147+
}
94148
//[EndpointDescription("Retrieve requests")]
95149
//[ProducesResponseType(typeof(CursorPagedResult<FriendSuggestionResponse>), StatusCodes.Status200OK)]
96150
//[Authorize]

Relationship.Application/GrpcServices/GrpcRelationshipService.cs

+9-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public override async Task<ProfileIdsResponse> getAllBlockerIds(ProfileRequest r
123123
response.Ids.AddRange(source);
124124
return response;
125125
}
126-
126+
127127
public override async Task<ProfileIdsResponse> getAllBlockeeIds(ProfileRequest request, ServerCallContext context)
128128
{
129129
logger.LogInformation("Get blockees for ProfileId: {ProfileId}", request.Id);
@@ -132,7 +132,14 @@ public override async Task<ProfileIdsResponse> getAllBlockeeIds(ProfileRequest r
132132
response.Ids.AddRange(source);
133133
return response;
134134
}
135-
135+
public override async Task<MutualFriendCountResponse> getFriendsOfMutualFriends(ProfileRequest request, ServerCallContext context)
136+
{
137+
logger.LogInformation("Get mutual friend count for ProfileId: {ProfileId}", request.Id);
138+
var source = await friendshipService.GetAllMutualFriendsWithCount(request.Id);
139+
var response = new MutualFriendCountResponse();
140+
response.ProfileIdsWithMutualCounts.AddRange(source.Select(mapper.Map<ProfileIdWithMutualCount>));
141+
return response;
142+
}
136143
public override async Task<MutualFriendCountResponse> countMutualFriends(MutualFriendCountRequest request, ServerCallContext context)
137144
{
138145
logger.LogInformation("Get mutual friend count for ProfileId: {ProfileId}", request.CurrentProfileId);

Relationship.Application/IServices/IFriendshipService.cs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public interface IFriendshipService
2222

2323
public Task<IList<string>> GetAllPendingRequestIds(string profile);
2424

25+
public Task<IList<string>> GetAllMutualFriendIds(string profile);
26+
27+
public Task<IList<ProfileIdWithMutualCount>> GetAllMutualFriendsWithCount(string profile);
28+
2529
public Task<IList<string>> GetAllRequestIds(string profile);
2630

2731
public Task<IList<string>> GetAllSentRequestIds(string profile);

Relationship.Application/Services/FriendshipService.cs

+19-3
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,11 @@ public async Task<IList<string>> GetAllPendingRequestIds(string profileId)
216216

217217
public async Task<IList<ProfileIdWithMutualCount>> CountMutualFriends(string currentProfileId, IList<string> profileIds)
218218
{
219-
var list = await friendshipRepository.CountMutualFriends(profileIds, Guid.Parse(currentProfileId));
220-
return list.Select(item => new ProfileIdWithMutualCount
219+
var list = profileIds.Select(x => Guid.Parse(x)).ToList();
220+
var friendsOfMutualFriends = await friendshipRepository.GetMutualFriendsAndCount(Guid.Parse(currentProfileId), list);
221+
return friendsOfMutualFriends.Select(item => new ProfileIdWithMutualCount
221222
{
222-
ProfileId = item.FriendId.ToString(),
223+
ProfileId = item.MutualFriendId.ToString(),
223224
Count = item.MutualFriendCount
224225
}).ToList();
225226
}
@@ -271,6 +272,21 @@ private async Task PublishFriendshipNotificationCommands(Friendship entity)
271272

272273
await messageBus.Publish(notificationCommand);
273274
}
275+
public async Task<IList<ProfileIdWithMutualCount>> GetAllMutualFriendsWithCount(string profile)
276+
{
277+
278+
var list = await friendshipRepository.GetFriendsOfMutualFriend(Guid.Parse(profile));
279+
var friendsOfMutualFriends = await friendshipRepository.GetMutualFriendsAndCount(Guid.Parse(profile), list);
280+
return friendsOfMutualFriends.Select(item => new ProfileIdWithMutualCount
281+
{
282+
ProfileId = item.MutualFriendId.ToString(),
283+
Count = item.MutualFriendCount
284+
}).ToList();
285+
}
274286

287+
public Task<IList<string>> GetAllMutualFriendIds(string profile)
288+
{
289+
throw new NotImplementedException();
290+
}
275291
}
276292
}

Relationship.Domain/Repositories/IFriendshipRepository.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ public interface IFriendshipRepository : ISqlRepository<Friendship, Guid>
2727

2828
Task<int> CountMutualFriends(Guid profileId, Guid currentProfile);
2929

30-
Task<IList<Guid>> GetAllFriendIdsOfCurrentUserAsync(Guid currentUserId);
31-
3230
Task<IList<Guid>> GetAllMutualFriendIdsAsync(Guid currentUserId, IList<Guid> friendsOfCurrentUser);
3331

32+
Task<IList<(Guid MutualFriendId, int MutualFriendCount)>> GetMutualFriendsAndCount(Guid currentUserId, IList<Guid> friendsOfMutualFriend);
33+
34+
Task<IList<Guid>> GetFriendsOfMutualFriend(Guid currentUserId);
35+
3436
Task<IList<(Guid FriendId, int MutualFriendCount)>> CountMutualFriends(IList<string> results, Guid currentUserId);
3537

3638
Task<IList<Guid>> GetAllRequestIdsAsync(Guid currentUserId);

Relationship.Infrastructure/Repositories/FriendshipRepository.cs

+58-19
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,48 @@ public async Task<IList<Guid>> GetAllMutualFriendIdsAsync(Guid currentUserId, IL
6060
.Distinct()
6161
.ToListAsync();
6262
}
63-
64-
public async Task<IList<Guid>> GetAllFriendIdsOfCurrentUserAsync(Guid currentUserId)
63+
64+
public async Task<IList<Guid>> GetFriendsOfMutualFriend(Guid currentUserId)
6565
{
66-
return await context.Friendships
67-
.Where(f => (f.SenderId == currentUserId || f.ReceiverId == currentUserId) && f.Status == FriendshipStatus.Connected )
68-
.Select(f => f.SenderId == currentUserId ? f.ReceiverId : f.SenderId)
66+
var friendsOfUser = await DbSet
67+
.Where(f1 => (f1.SenderId == currentUserId || f1.ReceiverId == currentUserId) && f1.Status == FriendshipStatus.Connected)
68+
.Select(f1 => f1.SenderId == currentUserId ? f1.ReceiverId : f1.SenderId)
69+
.ToListAsync();
70+
71+
var mutualFriends = await DbSet
72+
.Where(f2 => friendsOfUser.Contains(f2.SenderId) || friendsOfUser.Contains(f2.ReceiverId))
73+
.Where(f2 => f2.Status == FriendshipStatus.Connected && f2.SenderId != currentUserId && f2.ReceiverId != currentUserId)
74+
.Select(f2 => friendsOfUser.Contains(f2.SenderId) ? f2.ReceiverId : f2.SenderId)
75+
.Distinct()
6976
.ToListAsync();
77+
78+
return mutualFriends;
79+
}
80+
81+
public int GetMutualFriendCount(IList<Guid> currentUserFiends, IList<Guid> friendOfFriends)
82+
{
83+
var mutualFriends = currentUserFiends.Intersect(friendOfFriends).ToList();
84+
85+
int mutualFriendCount = mutualFriends.Count;
86+
87+
return mutualFriendCount;
88+
}
89+
90+
public async Task<IList<(Guid MutualFriendId, int MutualFriendCount)>> GetMutualFriendsAndCount(Guid currentUserId, IList<Guid> friendsOfMutualFriend)
91+
{
92+
var friendsOfUser = await GetAllFriendIdsAsync(currentUserId);
93+
94+
var friendsOfMutualFriendAndCount = new List<(Guid MutualFriendId, int MutualFriendCount)>();
95+
96+
foreach (var friend in friendsOfMutualFriend)
97+
{
98+
var mutualFriendFriends = await GetAllFriendIdsAsync(friend);
99+
100+
var mutualFriendCount = GetMutualFriendCount(friendsOfUser, mutualFriendFriends);
101+
102+
friendsOfMutualFriendAndCount.Add((MutualFriendId: friend, MutualFriendCount: mutualFriendCount));
103+
}
104+
return friendsOfMutualFriendAndCount;
70105
}
71106

72107
public async Task<IList<Guid>> GetAllPendingRequestIdsAsync(Guid currentUserId)
@@ -93,22 +128,26 @@ public async Task<IList<Guid>> GetAllSentRequestIdsAsync(Guid currentUserId)
93128
.ToListAsync();
94129
}
95130

96-
public async Task<IList<(Guid FriendId, int MutualFriendCount)>> CountMutualFriends(IList<string> results, Guid currentUserId)
131+
public async Task<IList<(Guid FriendId, int MutualFriendCount)>> CountMutualFriends(IList<string> friendIds, Guid currentUserId)
97132
{
98-
var resultGuids = results.Select(Guid.Parse).ToList();
99-
var queryResult = await context.Friendships
100-
.Where(f => resultGuids.Contains(f.SenderId) || resultGuids.Contains(f.ReceiverId))
101-
.Where(f => f.SenderId != currentUserId && f.ReceiverId != currentUserId)
102-
.Select(f => f.SenderId == currentUserId ? f.ReceiverId : f.SenderId)
103-
.GroupBy(friendId => friendId)
104-
.Select(group => new
105-
{
106-
FriendId = group.Key,
107-
Count = group.Count()
108-
})
109-
.ToListAsync();
133+
var mutualFriendCounts = await context.Friendships
134+
.Where(f1 => (f1.SenderId == currentUserId || f1.ReceiverId == currentUserId) && f1.Status == FriendshipStatus.Connected)
135+
.Join(
136+
context.Friendships,
137+
f1 => f1.SenderId == currentUserId ? f1.ReceiverId : f1.SenderId,
138+
f2 => f2.SenderId == currentUserId ? f2.ReceiverId : f2.SenderId,
139+
(f1, f2) => new { FriendA = f1.SenderId == currentUserId ? f1.ReceiverId : f1.SenderId, FriendB = f2.SenderId == currentUserId ? f2.ReceiverId : f2.SenderId }
140+
)
141+
.Where(match => friendIds.Contains(match.FriendB.ToString()))
142+
.GroupBy(match => match.FriendB)
143+
.Select(group => new
144+
{
145+
FriendId = group.Key,
146+
MutualFriendCount = group.Count()
147+
})
148+
.ToListAsync();
110149

111-
return queryResult.Select(x => (x.FriendId, x.Count)).ToList();
150+
return mutualFriendCounts.Select(x => (x.FriendId, x.MutualFriendCount)).ToList();
112151
}
113152

114153
}

Relationship.Presentation/Controllers/FriendshipController.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ public async Task<IActionResult> GetFriends([FromQuery] string nextCursor, [From
203203
var friends = await friendshipService.GetFriends(currentProfileId, nextCursor, limit);
204204

205205
// Tập hợp toàn bộ các ID cần nạp trước
206-
var profileIds = friends.Items.Select(item => item.SenderId.ToString()).Distinct();
207-
profileIds.ToList().Add(currentProfileId);
206+
var profileIds = friends.Items.Select(item => currentProfileId.Equals(item.SenderId.ToString()) ? item.ReceiverId.ToString() : item.SenderId.ToString()).Distinct();
207+
//profileIds.ToList().Add(currentProfileId);
208208

209209
// Nạp toàn bộ profiles cần thiết
210210
var profiles = await commonProfileClient.GetProfiles(profileIds.ToList());
@@ -222,14 +222,15 @@ public async Task<IActionResult> GetFriends([FromQuery] string nextCursor, [From
222222
});
223223
var photoMetadataDict = (await Task.WhenAll(photoMetadataTasks)).ToDictionary(x => x.Id, x => x.Metadata);
224224

225-
var resultHasCount = await friendshipService.CountMutualFriends(currentProfileId, friends.Items.Select(f => f.SenderId.ToString()).ToList());
225+
var resultHasCount = await friendshipService.CountMutualFriends(currentProfileId, friends.Items.Select(f => currentProfileId.Equals(f.SenderId.ToString()) ? f.ReceiverId.ToString() : f.SenderId.ToString()).ToList());
226226

227227
var resultHasCountDict = resultHasCount.ToDictionary(p => p.ProfileId);
228228

229229
IList<FriendshipResponse> result = [];
230230
foreach (var item in friends.Items)
231231
{
232-
if (profileDict.TryGetValue(item.SenderId, out var profile))
232+
var profileId = currentProfileId.Equals(item.SenderId.ToString()) ? item.ReceiverId : item.SenderId;
233+
if (profileDict.TryGetValue(profileId, out var profile))
233234
{
234235
if (profile.Avatar != null)
235236
{

0 commit comments

Comments
 (0)