Deduplicate post search results

This commit is contained in:
Tim
2025-07-01 23:14:03 +08:00
parent 26e624c43b
commit 0b424805e5
2 changed files with 70 additions and 5 deletions

View File

@@ -11,7 +11,9 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.LinkedHashMap;
import java.util.stream.Stream;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@@ -46,13 +48,29 @@ public class SearchService {
public List<SearchResult> globalSearch(String keyword) {
Stream<SearchResult> users = searchUsers(keyword).stream()
.map(u -> new SearchResult("user", u.getId(), u.getUsername()));
Stream<SearchResult> posts = searchPosts(keyword).stream()
.map(p -> new SearchResult("post", p.getId(), p.getTitle()));
Stream<SearchResult> titles = searchPostsByTitle(keyword).stream()
.map(p -> new SearchResult("post_title", p.getId(), p.getTitle()));
// Merge post results while removing duplicates between search by content
// and search by title
List<SearchResult> mergedPosts = Stream.concat(
searchPosts(keyword).stream()
.map(p -> new SearchResult("post", p.getId(), p.getTitle())),
searchPostsByTitle(keyword).stream()
.map(p -> new SearchResult("post_title", p.getId(), p.getTitle()))
)
.collect(java.util.stream.Collectors.toMap(
SearchResult::id,
sr -> sr,
(a, b) -> a,
java.util.LinkedHashMap::new
))
.values()
.stream()
.toList();
Stream<SearchResult> comments = searchComments(keyword).stream()
.map(c -> new SearchResult("comment", c.getId(), c.getContent()));
return Stream.concat(Stream.concat(Stream.concat(users, posts), titles), comments)
return Stream.concat(Stream.concat(users, mergedPosts.stream()), comments)
.toList();
}

View File

@@ -0,0 +1,47 @@
package com.openisle.service;
import com.openisle.model.Post;
import com.openisle.model.PostStatus;
import com.openisle.repository.CommentRepository;
import com.openisle.repository.PostRepository;
import com.openisle.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class SearchServiceTest {
@Test
void globalSearchDeduplicatesPosts() {
UserRepository userRepo = Mockito.mock(UserRepository.class);
PostRepository postRepo = Mockito.mock(PostRepository.class);
CommentRepository commentRepo = Mockito.mock(CommentRepository.class);
SearchService service = new SearchService(userRepo, postRepo, commentRepo);
Post post1 = new Post();
post1.setId(1L);
post1.setTitle("hello");
Post post2 = new Post();
post2.setId(2L);
post2.setTitle("world");
Mockito.when(postRepo.findByTitleContainingIgnoreCaseOrContentContainingIgnoreCaseAndStatus(
Mockito.anyString(), Mockito.anyString(), Mockito.eq(PostStatus.PUBLISHED)))
.thenReturn(List.of(post1));
Mockito.when(postRepo.findByTitleContainingIgnoreCaseAndStatus(Mockito.anyString(), Mockito.eq(PostStatus.PUBLISHED)))
.thenReturn(List.of(post1, post2));
Mockito.when(commentRepo.findByContentContainingIgnoreCase(Mockito.anyString()))
.thenReturn(List.of());
Mockito.when(userRepo.findByUsernameContainingIgnoreCase(Mockito.anyString()))
.thenReturn(List.of());
List<SearchService.SearchResult> results = service.globalSearch("h");
assertEquals(2, results.size());
assertEquals(1L, results.get(0).id());
assertEquals(2L, results.get(1).id());
}
}