Skip to content

[Fix] 검색 오류, 리뷰 작성 기능 수정#134

Merged
marshmallowing merged 3 commits intodevelopfrom
feature/128
Feb 16, 2026
Merged

[Fix] 검색 오류, 리뷰 작성 기능 수정#134
marshmallowing merged 3 commits intodevelopfrom
feature/128

Conversation

@marshmallowing
Copy link
Copy Markdown
Member

@marshmallowing marshmallowing commented Feb 16, 2026

🔍️ 작업 내용

✨ 상세 설명

  • 검색 기능 수정
    • 자동완성 결과를 카테고리/브랜드 우선순위 고정 방식 → ES 점수 기반 일치율 순 정렬로 변경
    • 추천 검색어 로그 저장 버그 수정: 검색 결과 첫 번째 상품의 브랜드명을 저장하던 방식 → ES에서 입력 query와 가장 일치하는 대표 키워드(브랜드/카테고리/상품명)를 추출해 저장하도록 변경 (오타 입력 시에도 정규화된 키워드 저장)
  • 리뷰 기능 수정
    • initializeReview: 동일 orderItemId에 DRAFT 리뷰가 이미 존재하면 새로 생성하지 않고 기존 리뷰 ID 반환
    • 작성 가능한 리뷰 목록 조회: DRAFT 상태 목록에 노출되도록 수정
    • 작성 가능한 리뷰 응답에 reviewId, reviewStatus 필드 추가
    • 1차 답변 응답값 displayName → enum name으로 변경
    • 1차 답변 응답값에 긍정/부정 필드 추가

🛠️ 추후 리팩토링 및 고도화 계획

📸 스크린샷 (선택)

💬 리뷰 요구사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 리뷰 초안 저장·재개 기능 추가
    • 검색어에서 대표 키워드 추출 기능 추가
  • 개선사항

    • 리뷰 상세·대기 응답에 의류 카테고리, 상태 및 리뷰 ID 노출
    • 1단계 답변에 사이즈/소재 보조 유형 정보 추가
    • 이슈 부위 및 소재 특성을 리스트로 반환
  • 최적화

    • 자동완성 결과 순서 개선 및 초안 생성 동시성/중복 처리 강화

@marshmallowing marshmallowing self-assigned this Feb 16, 2026
@marshmallowing marshmallowing added 🐞 Fix 버그 수정 ♻️ Refactor 리팩토링 labels Feb 16, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 16, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

검색 대표 키워드 추출 메서드 추가 및 ProductService 연동, 리뷰 도메인에 드래프트 상태 분기 도입과 의류 카테고리 및 사이즈/재질 보조 타입 필드 추가 등 리뷰 생성·조회 흐름이 draft-aware 하게 변경되었습니다.

Changes

Cohort / File(s) Summary
Search / Product
src/main/java/com/ongil/backend/domain/product/service/ProductService.java, src/main/java/com/ongil/backend/domain/search/service/SearchService.java
검색 대표 키워드 추출 로직을 SearchService.extractRepresentativeKeyword(query)로 분리. getAutocomplete 합쳐진 집합으로 재구성 및 새 public 메서드 추가.
Review DTOs (Responses)
src/main/java/com/ongil/backend/domain/review/dto/response/PendingReviewResponse.java, src/main/java/com/ongil/backend/domain/review/dto/response/ReviewDetailResponse.java, src/main/java/com/ongil/backend/domain/review/dto/response/ReviewStep1Response.java
clothingCategory, reviewId, reviewStatus, sizeSecondaryType, materialSecondaryType 필드 추가. InitialSecondAnswers의 일부 필드를 List<String>으로 변경. ReviewStep1Response.of 시그니처 확장.
Review Converters
src/main/java/com/ongil/backend/domain/review/converter/ReviewConverter.java, src/main/java/com/ongil/backend/domain/review/converter/ReviewWriteConverter.java
product → clothingCategory 파싱 로직 추가, Size/Material 보조 타입 계산 로직 추가. toPendingReviewResponse 시그니처에 draftReview 파라미터 추가.
Review Repository / Entity / Validator
src/main/java/com/ongil/backend/domain/review/repository/ReviewRepository.java, src/main/java/com/ongil/backend/domain/review/entity/Review.java, src/main/java/com/ongil/backend/domain/review/validator/ReviewValidator.java
리뷰 테이블에 (order_item_id, review_type, review_status) 복합 유니크 제약 추가. findByOrderItemIdAndReviewTypeAndReviewStatus 추가 및 검증 메서드명 validateInitialReviewAlreadyCompleted로 변경.
Review Services (Command & Query)
src/main/java/com/ongil/backend/domain/review/service/ReviewCommandService.java, src/main/java/com/ongil/backend/domain/review/service/ReviewQueryService.java
초기 리뷰 생성 시 기존 DRAFT 재사용 로직 추가, 동시성(DataIntegrityViolation) 처리 추가. Pending 조회는 COMPLETED 존재 여부 확인 후 DRAFT를 조회해 컨버터에 전달하도록 변경.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ReviewService as ReviewCommandService
    participant Repo as ReviewRepository
    participant DB

    Client->>ReviewService: initializeReview(orderItemId)
    ReviewService->>Repo: findByOrderItemIdAndReviewTypeAndReviewStatus(orderItemId, INITIAL, DRAFT)
    alt draft exists
        Repo-->>ReviewService: Optional<DRAFT review>
        ReviewService-->>Client: return draft.id
    else no draft
        ReviewService->>DB: save new DRAFT review (saveAndFlush)
        alt concurrent insert causes DataIntegrityViolation
            DB-->>ReviewService: DataIntegrityViolationException
            ReviewService->>Repo: findByOrderItemIdAndReviewTypeAndReviewStatus(..., DRAFT)
            Repo-->>ReviewService: Optional<DRAFT review>
            ReviewService-->>Client: return existing draft.id
        else success
            DB-->>ReviewService: persisted review.id
            ReviewService-->>Client: return new review.id
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • neibler
  • kangcheolung
🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 검색 오류 및 리뷰 작성 기능 수정이라는 주요 변경 사항을 명확하게 요약하고 있습니다.
Linked Issues check ✅ Passed PR의 코드 변경사항이 연결된 이슈 #128의 목표(추천 검색어, 검색어 자동 완성, 리뷰 작성 API 연동)를 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #128에서 명시한 검색 및 리뷰 기능과 관련되어 있으며 범위를 벗어난 변경은 없습니다.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into develop

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/128

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/java/com/ongil/backend/domain/review/service/ReviewQueryService.java (1)

152-177: 🛠️ Refactor suggestion | 🟠 Major

N+1 쿼리 문제: 주문 아이템별 개별 조회

OrderItem마다 최대 4번의 DB 쿼리가 실행됩니다:

  1. existsBy...(INITIAL, COMPLETED)
  2. findBy...(INITIAL, DRAFT)
  3. existsBy...(ONE_MONTH, COMPLETED)
  4. findBy...(ONE_MONTH, DRAFT)

주문 아이템이 많은 사용자의 경우 심각한 성능 저하가 발생할 수 있습니다. getPendingReviewCount (Line 183)에서는 이미 findReviewedOrderItemIds로 배치 조회하고 있으므로, 동일한 패턴을 여기에도 적용하는 것이 좋습니다.

♻️ 배치 조회 기반 리팩토링 제안
 public List<PendingReviewResponse> getPendingReviews(Long userId) {
     List<PendingReviewResponse> pendingReviews = new ArrayList<>();
     List<OrderItem> orderItems = orderItemRepository.findByOrderUserIdWithProduct(userId);
+    List<Long> orderItemIds = orderItems.stream().map(OrderItem::getId).toList();
+    if (orderItemIds.isEmpty()) return pendingReviews;
+
+    // 배치로 COMPLETED 리뷰 존재 여부 확인
+    List<Long> initialCompletedIds = reviewRepository.findReviewedOrderItemIds(orderItemIds, ReviewType.INITIAL);
+    List<Long> oneMonthCompletedIds = reviewRepository.findReviewedOrderItemIds(orderItemIds, ReviewType.ONE_MONTH);
+
+    // 배치로 DRAFT 리뷰 조회 (새로운 repository 메서드 필요)
+    // Map<Long, Review> initialDrafts = ...
+    // Map<Long, Review> oneMonthDrafts = ...

     for (OrderItem orderItem : orderItems) {
         LocalDateTime orderDate = orderItem.getOrder().getCreatedAt();
-        if (!reviewRepository.existsByOrderItemIdAndReviewTypeAndReviewStatus(orderItem.getId(), ReviewType.INITIAL, ReviewStatus.COMPLETED)) {
-            Review draftReview = reviewRepository.findByOrderItemIdAndReviewTypeAndReviewStatus(
-                orderItem.getId(), ReviewType.INITIAL, ReviewStatus.DRAFT).orElse(null);
-            pendingReviews.add(reviewConverter.toPendingReviewResponse(orderItem, ReviewType.INITIAL, draftReview));
+        if (!initialCompletedIds.contains(orderItem.getId())) {
+            // DRAFT 조회는 배치 맵에서 가져옴
+            pendingReviews.add(reviewConverter.toPendingReviewResponse(orderItem, ReviewType.INITIAL, /* draftFromMap */ null));
         }
         // ... ONE_MONTH도 동일 패턴
     }
src/main/java/com/ongil/backend/domain/review/converter/ReviewConverter.java (1)

73-79: ⚠️ Potential issue | 🔴 Critical

buildAnswerSummarybuildMyReviewAnswerSummary에서 null 답변에 대한 NPE 위험 존재

sizeAnswer, colorAnswer, materialAnswer는 Review 엔티티에서 nullable 필드이며, 이들 메서드는 null 체크 없이 .getDisplayName()을 직접 호출합니다.

현재 리포지토리 쿼리는 모두 ReviewStatus.COMPLETED 필터링을 명시적으로 적용하므로 DRAFT 리뷰는 리스트 조회에 포함되지 않습니다. 하지만 COMPLETED 상태의 리뷰도 답변 필드가 null일 수 있으므로, buildInitialFirstAnswers (라인 153에서 null 체크)와의 일관성을 맞추기 위해 양쪽 메서드 모두 null 체크를 추가해야 합니다.

🤖 Fix all issues with AI agents
In
`@src/main/java/com/ongil/backend/domain/review/converter/ReviewConverter.java`:
- Around line 141-145: Extract the duplicated mapping into a private helper
method (e.g., private ClothingCategory resolveClothingCategory(Product product))
inside ReviewConverter that returns
Optional.ofNullable(product.getCategory()).map(Category::getParentCategory).map(Category::getName).map(ClothingCategory::fromDisplayName).orElse(null);
then replace the inlined expressions in buildProductInfo and
buildPendingProductInfo with
.clothingCategory(resolveClothingCategory(product)). Ensure the helper is
non-public, null-safe, and referenced by both methods to remove duplication.

In
`@src/main/java/com/ongil/backend/domain/review/dto/response/PendingReviewResponse.java`:
- Around line 51-53: The ClothingCategory enum is currently serialized as its
enum name (e.g., OUTER, TOP) but should return the human-friendly Korean
displayName; update the ClothingCategory enum by annotating its displayName
getter or field with `@JsonValue` so Jackson serializes the enum using
displayName, ensuring API responses (and the
PendingReviewResponse.clothingCategory property) return the expected Korean
strings.

In
`@src/main/java/com/ongil/backend/domain/review/dto/response/ReviewDetailResponse.java`:
- Around line 142-143: The `@Schema` description for the field
materialSecondaryType in ReviewDetailResponse is missing a closing parenthesis;
update the `@Schema` annotation on the materialSecondaryType field to include the
closing ')' so the description reads "소재 2차 질문 방향 (POSITIVE / NEGATIVE / null)".

In
`@src/main/java/com/ongil/backend/domain/review/repository/ReviewRepository.java`:
- Around line 205-206: The repository method
findByOrderItemIdAndReviewTypeAndReviewStatus can return duplicates under
concurrent requests because there's no DB unique constraint or pessimistic
locking; update to prevent duplicate DRAFT reviews by either: add a unique
constraint on the Review entity `@Table` for (order_item_id, review_type,
review_status); or annotate the repository method
findByOrderItemIdAndReviewTypeAndReviewStatus with
`@Lock`(LockModeType.PESSIMISTIC_WRITE); or apply a pessimistic lock during the
lookup inside ReviewCommandService.initializeReview before creating a new Review
so only one request can create the DRAFT for the same
orderItemId+reviewType+reviewStatus.

In `@src/main/java/com/ongil/backend/domain/search/service/SearchService.java`:
- Around line 118-129: The current loop over SearchHit<ProductDocument> (hits)
always inserts doc.getCategoryName() then getName() then getBrandName(), which
biases category values ahead of other fields even if a brand match had a higher
ES score; change to build a list of (score, value) pairs from each hit (use
hit.getScore() and the non-null results of
ProductDocument.getCategoryName()/getName()/getBrandName()), sort that flat list
by score descending, then iterate it to add values into the LinkedHashSet
suggestions (to dedupe while preserving the score-based order) and finally
return the first 12; update the code around the suggestions variable and the
hits loop accordingly.
🧹 Nitpick comments (6)
src/main/java/com/ongil/backend/domain/product/service/ProductService.java (1)

195-199: 검색 사이드 이펙트 로직 개선 확인

대표 키워드 추출을 SearchService로 위임하여 SRP를 잘 준수하고 있고, null/blank 방어 로직도 적절합니다.

다만, extractRepresentativeKeyword(query)는 ES 쿼리를 한 번 더 발생시킵니다. getProductIdsByQuery(query) 호출 시 이미 ES를 조회했으므로, 첫 조회 결과를 재활용하면 불필요한 네트워크 왕복을 줄일 수 있습니다.

src/main/java/com/ongil/backend/domain/search/service/SearchService.java (1)

170-196: 대표 키워드 추출 로직 검토

오타가 포함된 검색어도 ES가 매칭한 top hit에서 정규화된 키워드를 추출하는 접근이 합리적입니다. contains 체크 실패 시 fallback (categoryName > brandName)으로 처리하는 것도 적절합니다.

두 가지 개선 포인트:

  1. querynormalize() 없이 사용: getProductIdsByQuery에서는 normalize(query)를 거치지만, 이 메서드는 raw query를 그대로 사용합니다. autocomplete 필드 특성상 큰 문제는 아니나, 공백 전처리 등 일관성 차원에서 확인이 필요합니다.

  2. contains 기반 매칭의 한계: "나이키 신발".toLowerCase().contains("나이키") → true이지만, "나이킹".toLowerCase().contains("나이키") → false. 오타 케이스에서는 항상 fallback을 타게 되는데, fallback이 카테고리명을 반환하므로 brand 검색 시 대표 키워드가 brand가 아닌 category가 됩니다.

♻️ Levenshtein 거리 기반 매칭 또는 ES explain API 활용 제안
 // 가장 점수 높은 문서에서 query와 가장 유사한 필드 값 반환
 String q = query.toLowerCase();
-if (top.getBrandName() != null && top.getBrandName().toLowerCase().contains(q)) return top.getBrandName();
-if (top.getCategoryName() != null && top.getCategoryName().toLowerCase().contains(q)) return top.getCategoryName();
-if (top.getName() != null && top.getName().toLowerCase().contains(q)) return top.getName();
+// boost 순서(brand > category > name)를 활용하여,
+// ES가 어떤 필드에서 매칭했는지 highlight 또는 explain으로 판단하는 방안 고려
+if (top.getBrandName() != null && top.getBrandName().toLowerCase().contains(q)) return top.getBrandName();
+if (top.getCategoryName() != null && top.getCategoryName().toLowerCase().contains(q)) return top.getCategoryName();
+if (top.getName() != null && top.getName().toLowerCase().contains(q)) return top.getName();
src/main/java/com/ongil/backend/domain/review/converter/ReviewWriteConverter.java (1)

37-47: 매직 문자열 대신 enum 또는 상수 사용 권장

"POSITIVE" / "NEGATIVE" 문자열이 여러 곳에서 반복됩니다. 오타 위험이 있고, 타입 안전성이 없습니다.

♻️ enum 또는 상수 활용 제안
+// 예: 별도 enum 또는 상수 정의
+private static final String POSITIVE = "POSITIVE";
+private static final String NEGATIVE = "NEGATIVE";
+
 String sizeSecondaryType = null;
 if (needsSizeQ) {
     SizeAnswer sizeAnswer = review.getSizeAnswer();
     sizeSecondaryType = (sizeAnswer == SizeAnswer.LOOSE || sizeAnswer == SizeAnswer.TOO_BIG_NEED_ALTERATION)
-        ? "POSITIVE" : "NEGATIVE";
+        ? POSITIVE : NEGATIVE;
 }

 String materialSecondaryType = null;
 if (needsMaterialQ) {
-    materialSecondaryType = review.getMaterialAnswer().isPositive() ? "POSITIVE" : "NEGATIVE";
+    materialSecondaryType = review.getMaterialAnswer().isPositive() ? POSITIVE : NEGATIVE;
 }
src/main/java/com/ongil/backend/domain/review/dto/response/PendingReviewResponse.java (1)

21-26: DTO 필드 추가 확인

reviewIdreviewStatus 필드가 DRAFT 상태의 리뷰 정보를 프론트엔드에 전달하기 위해 적절히 추가되었습니다. Schema 설명도 명확합니다.

reviewStatusString 타입인 반면, 내부적으로는 ReviewStatus enum을 사용하고 있습니다. 프론트엔드와의 계약이 확정되어 있다면 괜찮지만, 타입 안전성을 위해 ReviewStatus enum을 직접 사용하는 것도 고려해볼 수 있습니다.

src/main/java/com/ongil/backend/domain/review/dto/response/ReviewStep1Response.java (1)

5-5: 사용되지 않는 @Schema import

io.swagger.v3.oas.annotations.media.Schema가 import되었지만, 이 클래스의 어떤 필드에도 @Schema 어노테이션이 적용되어 있지 않습니다. 같은 도메인의 다른 DTO(ReviewDetailResponse, PendingReviewResponse)는 모든 필드에 @Schema를 사용하고 있으므로, import를 제거하거나 각 필드에 @Schema 어노테이션을 추가하여 일관성을 맞추는 것을 권장합니다.

src/main/java/com/ongil/backend/domain/review/converter/ReviewConverter.java (1)

152-177: sizeSecondaryType/materialSecondaryType 판별 로직이 ReviewWriteConverter와 중복됩니다

Lines 160-169의 sizeSecondaryType/materialSecondaryType 산출 로직이 ReviewWriteConverter.toStep1Response (Snippet 2, lines 36-48)와 동일합니다. 두 곳에서 판별 조건이 독립적으로 유지되면, 향후 조건 변경 시 한쪽만 수정하는 실수가 발생할 수 있습니다.

공통 유틸리티 메서드(예: SizeAnswer.getSecondaryType(), MaterialAnswer.getSecondaryType())로 enum에 위임하거나, 공유 헬퍼로 추출하는 것을 권장합니다.

Comment on lines +51 to +53
@Schema(description = "상위 카테고리")
private ClothingCategory clothingCategory;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find ClothingCategory enum file
fd "ClothingCategory.java" -type f

Repository: IT-Cotato/12th-OnGil-BE

Length of output: 237


🏁 Script executed:

#!/bin/bash
# Find ClothingCategory enum file
fd "ClothingCategory.java" -t f

Repository: IT-Cotato/12th-OnGil-BE

Length of output: 140


🏁 Script executed:

#!/bin/bash
# Read ClothingCategory enum
cat -n src/main/java/com/ongil/backend/domain/review/enums/ClothingCategory.java

echo ""
echo "=== Check for Jackson annotations ==="
grep -n "JsonValue\|JsonFormat\|JsonProperty" src/main/java/com/ongil/backend/domain/review/enums/ClothingCategory.java || echo "No Jackson annotations found"

Repository: IT-Cotato/12th-OnGil-BE

Length of output: 1583


🏁 Script executed:

#!/bin/bash
# Read PendingReviewResponse.java
cat -n src/main/java/com/ongil/backend/domain/review/dto/response/PendingReviewResponse.java

echo ""
echo "=== Check for Jackson annotations on clothingCategory field ==="
grep -B3 -A3 "clothingCategory" src/main/java/com/ongil/backend/domain/review/dto/response/PendingReviewResponse.java || echo "Not found"

Repository: IT-Cotato/12th-OnGil-BE

Length of output: 2109


ClothingCategory enum을 displayName으로 직렬화되도록 수정 필요

ClothingCategory에 Jackson 직렬화 설정이 없어서, API 응답 시 enum의 이름(OUTER, TOP 등)이 그대로 노출됩니다. 그런데 enum 내 displayName 필드가 한글 값("아우터", "상의" 등)을 가지고 있어서, 프론트엔드에서 기대하는 형식과 불일치할 가능성이 높습니다.

displayName 필드에 @JsonValue 어노테이션을 추가하여 직렬화 시 한글명이 반환되도록 수정하세요.

🤖 Prompt for AI Agents
In
`@src/main/java/com/ongil/backend/domain/review/dto/response/PendingReviewResponse.java`
around lines 51 - 53, The ClothingCategory enum is currently serialized as its
enum name (e.g., OUTER, TOP) but should return the human-friendly Korean
displayName; update the ClothingCategory enum by annotating its displayName
getter or field with `@JsonValue` so Jackson serializes the enum using
displayName, ensuring API responses (and the
PendingReviewResponse.clothingCategory property) return the expected Korean
strings.

Comment on lines +118 to 129
// ES 점수 순서 그대로 카테고리/상품명/브랜드 모두 수집
LinkedHashSet<String> suggestions = new LinkedHashSet<>();
for (SearchHit<ProductDocument> hit : hits) {
ProductDocument doc = hit.getContent();

if (doc.getCategoryName() != null) categorySet.add(doc.getCategoryName());
if (doc.getBrandName() != null) brandSet.add(doc.getBrandName());
if (doc.getCategoryName() != null) suggestions.add(doc.getCategoryName());
if (doc.getName() != null) suggestions.add(doc.getName());
if (doc.getBrandName() != null) suggestions.add(doc.getBrandName());
}

List<String> suggestions = new ArrayList<>(categorySet);
suggestions.addAll(brandSet);

return suggestions.stream()
.limit(12)
.toList();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

자동완성 결과의 정렬 순서 주의

LinkedHashSet을 사용하여 ES 점수 기반으로 hit 간 순서는 보존됩니다. 그러나 각 hit 내부에서 categoryName → name → brandName 순으로 항상 고정 삽입되므로, 실제 결과는 순수한 ES 점수 순서가 아닙니다.

예를 들어, 1번 hit의 brandName이 가장 높은 점수 기여를 했더라도 categoryName이 먼저 추가됩니다. 의도된 동작이라면 괜찮지만, PR 목적("ES score-based relevance sorting")과 약간 차이가 있을 수 있습니다.

🤖 Prompt for AI Agents
In `@src/main/java/com/ongil/backend/domain/search/service/SearchService.java`
around lines 118 - 129, The current loop over SearchHit<ProductDocument> (hits)
always inserts doc.getCategoryName() then getName() then getBrandName(), which
biases category values ahead of other fields even if a brand match had a higher
ES score; change to build a list of (score, value) pairs from each hit (use
hit.getScore() and the non-null results of
ProductDocument.getCategoryName()/getName()/getBrandName()), sort that flat list
by score descending, then iterate it to add values into the LinkedHashSet
suggestions (to dedupe while preserving the score-based order) and finally
return the first 12; update the code around the suggestions variable and the
hits loop accordingly.

@marshmallowing marshmallowing merged commit cce9470 into develop Feb 16, 2026
1 check was pending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐞 Fix 버그 수정 ♻️ Refactor 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Fix] 오류 수정

1 participant