[Developer] #533 언급 적은 식당 제외 필터 (min_mentions + video_count)
- backend: findAll 응답에 video_count(strong/unknown 링크수) + min_mentions 서버필터 - Restaurant.videoCount, RestaurantMapper(xml/iface), Service, Controller(+cache key) - frontend: Restaurant.video_count 타입 + 데스크톱 툴바 "언급"(2/3/5회+) 클라 필터 - 검증: min_mentions=2→116, =3→36 (위반 0). 빌드/tsc 통과 - 설계서 docs/design/533-min-mentions-filter/README.md Refs #533 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -56,17 +56,18 @@ public class RestaurantController {
|
||||
@RequestParam(defaultValue = "0") int offset,
|
||||
@RequestParam(required = false) String cuisine,
|
||||
@RequestParam(required = false) String region,
|
||||
@RequestParam(required = false) String channel) {
|
||||
@RequestParam(required = false) String channel,
|
||||
@RequestParam(name = "min_mentions", required = false) Integer minMentions) {
|
||||
if (limit > 500) limit = 500;
|
||||
String key = cache.makeKey("restaurants", "l=" + limit, "o=" + offset,
|
||||
"c=" + cuisine, "r=" + region, "ch=" + channel);
|
||||
"c=" + cuisine, "r=" + region, "ch=" + channel, "mm=" + minMentions);
|
||||
String cached = cache.getRaw(key);
|
||||
if (cached != null) {
|
||||
try {
|
||||
return objectMapper.readValue(cached, new TypeReference<List<Restaurant>>() {});
|
||||
} catch (Exception e) { log.warn("Cache deserialize failed, evicting: {}", e.getMessage()); cache.del(key); }
|
||||
}
|
||||
var result = restaurantService.findAll(limit, offset, cuisine, region, channel);
|
||||
var result = restaurantService.findAll(limit, offset, cuisine, region, channel, minMentions, false);
|
||||
cache.set(key, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -39,4 +39,7 @@ public class Restaurant {
|
||||
// Transient enrichment fields
|
||||
private List<String> channels;
|
||||
private List<String> foodsMentioned;
|
||||
|
||||
// #533 — 의미있는(strong/unknown) 영상 언급 수
|
||||
private Integer videoCount;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public interface RestaurantMapper {
|
||||
@Param("cuisine") String cuisine,
|
||||
@Param("region") String region,
|
||||
@Param("channel") String channel,
|
||||
@Param("minMentions") Integer minMentions,
|
||||
@Param("includeHidden") boolean includeHidden);
|
||||
|
||||
// #322 LLM 검증: hidden 표시 갱신
|
||||
|
||||
@@ -21,11 +21,13 @@ public class RestaurantService {
|
||||
}
|
||||
|
||||
public List<Restaurant> findAll(int limit, int offset, String cuisine, String region, String channel) {
|
||||
return findAll(limit, offset, cuisine, region, channel, false);
|
||||
return findAll(limit, offset, cuisine, region, channel, null, false);
|
||||
}
|
||||
|
||||
public List<Restaurant> findAll(int limit, int offset, String cuisine, String region, String channel, boolean includeHidden) {
|
||||
List<Restaurant> restaurants = mapper.findAll(limit, offset, cuisine, region, channel, includeHidden);
|
||||
// #533 — minMentions: 의미있는 언급 수가 N 미만인 식당 제외 (null/0이면 미적용)
|
||||
public List<Restaurant> findAll(int limit, int offset, String cuisine, String region, String channel,
|
||||
Integer minMentions, boolean includeHidden) {
|
||||
List<Restaurant> restaurants = mapper.findAll(limit, offset, cuisine, region, channel, minMentions, includeHidden);
|
||||
enrichRestaurants(restaurants);
|
||||
return restaurants;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<result property="hidden" column="hidden" javaType="java.lang.Boolean"/>
|
||||
<result property="hiddenReason" column="hidden_reason"/>
|
||||
<result property="verifiedAt" column="verified_at"/>
|
||||
<result property="videoCount" column="video_count"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- ===== Queries ===== -->
|
||||
@@ -33,7 +34,9 @@
|
||||
SELECT DISTINCT r.id, r.name, r.address, r.region, r.latitude, r.longitude,
|
||||
r.cuisine_type, r.price_range, r.google_place_id, r.tabling_url, r.catchtable_url,
|
||||
r.business_status, r.rating, r.rating_count, r.updated_at,
|
||||
r.hidden, r.hidden_reason, r.verified_at
|
||||
r.hidden, r.hidden_reason, r.verified_at,
|
||||
(SELECT COUNT(*) FROM video_restaurants vrc
|
||||
WHERE vrc.restaurant_id = r.id AND vrc.relevance IN ('strong','unknown')) AS video_count
|
||||
FROM restaurants r
|
||||
<if test="channel != null and channel != ''">
|
||||
JOIN video_restaurants vr_f ON vr_f.restaurant_id = r.id
|
||||
@@ -55,6 +58,10 @@
|
||||
<if test="channel != null and channel != ''">
|
||||
AND c_f.channel_name = #{channel}
|
||||
</if>
|
||||
<if test="minMentions != null and minMentions > 0">
|
||||
AND (SELECT COUNT(*) FROM video_restaurants vrc
|
||||
WHERE vrc.restaurant_id = r.id AND vrc.relevance IN ('strong','unknown')) >= #{minMentions}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY r.updated_at DESC
|
||||
OFFSET #{offset} ROWS FETCH NEXT #{limit} ROWS ONLY
|
||||
|
||||
Reference in New Issue
Block a user