diff --git a/src/main/java/com/meetkey/server/domain/match/dto/RecommendationReqDTO.java b/src/main/java/com/meetkey/server/domain/match/dto/RecommendationReqDTO.java index 24e56ea..27ff170 100644 --- a/src/main/java/com/meetkey/server/domain/match/dto/RecommendationReqDTO.java +++ b/src/main/java/com/meetkey/server/domain/match/dto/RecommendationReqDTO.java @@ -4,6 +4,7 @@ import com.meetkey.server.domain.member.enums.InterestType; import com.meetkey.server.domain.member.enums.Language; import com.meetkey.server.domain.member.enums.Level; +import com.meetkey.server.domain.member.enums.*; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; @@ -25,6 +26,9 @@ public record RecommendationReqDTO( @Schema(description = "학습 언어 레벨 필터", example = "[\"BEGINNER\"]") List targetLanguageLevel, + @Schema(description = "성향(Personality) 태그 리스트 (예: [\"EXTROVERT\", \"GROUP\"])", example = "[\"EXTROVERT\", \"GROUP\"]") + List personalities, + @Schema(description = "최소 나이 (18세 이상)", example = "20") @Min(value = 18, message = "최소 나이는 18세 이상이어야 합니다.") Integer minAge, diff --git a/src/main/java/com/meetkey/server/domain/match/repository/MatchRepositoryImpl.java b/src/main/java/com/meetkey/server/domain/match/repository/MatchRepositoryImpl.java index f409063..b4e1510 100644 --- a/src/main/java/com/meetkey/server/domain/match/repository/MatchRepositoryImpl.java +++ b/src/main/java/com/meetkey/server/domain/match/repository/MatchRepositoryImpl.java @@ -4,9 +4,10 @@ import com.meetkey.server.domain.member.entity.Member; import com.meetkey.server.domain.member.entity.QInterest; import com.meetkey.server.domain.member.entity.QMember; +import com.meetkey.server.domain.member.entity.QPreference; import com.meetkey.server.domain.member.entity.mapping.QInterestMember; import com.meetkey.server.domain.member.entity.mapping.QMemberLocation; -import com.meetkey.server.domain.member.enums.Status; +import com.meetkey.server.domain.member.enums.*; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.NumberExpression; @@ -14,6 +15,7 @@ import lombok.RequiredArgsConstructor; import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; @RequiredArgsConstructor @@ -77,6 +79,65 @@ public List findRecommendableMembers(Member member, RecommendationReqDTO builder.and(distanceExpression.loe(request.maxDistance())); } + // 3. 성향 필터 (Preference Join) + // 3. 성향 필터 (Preference Join + Single List Parsing) + if (request.personalities() != null && !request.personalities().isEmpty()) { + QPreference qPreference = QPreference.preference; + query.leftJoin(qPreference).on(qPreference.member.eq(qMember)); + + List personalities = request.personalities(); + + // Enum 별 분류 리스트 + List socialTypes = new ArrayList<>(); + List meetingTypes = new ArrayList<>(); + List chatTypes = new ArrayList<>(); + List friendTypes = new ArrayList<>(); + List relationTypes = new ArrayList<>(); + + for (String p : personalities) { + // Ignore "ANY" or duplicates in logic if handled by isValidEnum + try { + socialTypes.add(SocialType.valueOf(p)); + continue; + } catch (IllegalArgumentException e) { + } + + try { + // MeetingType.ANY 무시 or 로직에 따라 포함 (여기선 무시) + MeetingType mt = MeetingType.valueOf(p); + if (mt != MeetingType.ANY) meetingTypes.add(mt); + continue; + } catch (IllegalArgumentException e) { + } + + try { + chatTypes.add(ChatType.valueOf(p)); + continue; + } catch (IllegalArgumentException e) { + } + + try { + // FriendType.ANY 무시 + FriendType ft = FriendType.valueOf(p); + if (ft != FriendType.ANY) friendTypes.add(ft); + continue; + } catch (IllegalArgumentException e) { + } + + try { + relationTypes.add(RelationType.valueOf(p)); + continue; + } catch (IllegalArgumentException e) { + } + } + + if (!socialTypes.isEmpty()) builder.and(qPreference.socialType.in(socialTypes)); + if (!meetingTypes.isEmpty()) builder.and(qPreference.meetingType.in(meetingTypes)); + if (!chatTypes.isEmpty()) builder.and(qPreference.chatType.in(chatTypes)); + if (!friendTypes.isEmpty()) builder.and(qPreference.friendType.in(friendTypes)); + if (!relationTypes.isEmpty()) builder.and(qPreference.relationType.in(relationTypes)); + } + return query.where(builder) .limit(limit) .fetch();