Logo花火漫画开发文档
RPC 函数详情

漫画筛选与计数

get_comics_by_meta_filter 及三个 count_comics_by_* 计数函数

本页包含漫画列表页的核心筛选函数 get_comics_by_meta_filter 和三个配套计数函数,主要用于分类浏览、作者页、标签页等列表场景。


get_comics_by_meta_filter

按元数据条件(年份、连载状态、分类、作者)分页筛选漫画,同时返回匹配总数用于分页。

函数签名

CREATE FUNCTION get_comics_by_meta_filter(
  p_filter_type  text,
  p_year         text     DEFAULT NULL,
  p_is_finished  boolean  DEFAULT NULL,
  p_category_id  bigint   DEFAULT NULL,
  p_author_name  text     DEFAULT NULL,
  p_offset       integer  DEFAULT 0,
  p_limit        integer  DEFAULT 20
) RETURNS TABLE (
  id, title, summary, cover_url, poster_url,
  category_id, categories,  -- jsonb,LEFT JOIN categories 整行
  lock_status, is_finished, has_upscaled,
  release_date, region, authors,
  rating_average, rating_count,
  popularity_daily, popularity_weekly, popularity_monthly,
  created_at, updated_at,
  latest_chapter_title, latest_chapter_updated_at,
  total_count  -- window count(*) over()
) LANGUAGE sql STABLE;

参数

参数类型默认值说明
p_filter_typetext必填筛选类型,取值见下方
p_yeartextNULL发行年份,格式 "2024",仅 RELEASE_YEAR 时使用
p_is_finishedbooleanNULL是否完结,仅 SERIAL_STATUS 时使用
p_category_idbigintNULL分类 ID,仅 CATEGORY 时使用
p_author_nametextNULL作者名(精确匹配 authors 数组元素),仅 AUTHOR 时使用
p_offsetinteger0分页偏移,自动 greatest(p_offset, 0)
p_limitinteger20每页条数,自动钳制到 [1, 100]

p_filter_type 取值

所需参数筛选逻辑
RELEASE_YEARp_yearrelease_date 落在该年份范围内,年份需匹配 ^\d{4}$
SERIAL_STATUSp_is_finishedis_finished 等于指定值
CATEGORYp_category_idcategory_id 等于指定值
AUTHORp_author_nameauthors 数组包含指定作者名(精确匹配,自动 trim)

p_filter_type 与对应参数不匹配时(如传 CATEGORYp_category_id 为 NULL),WHERE 条件为 false,返回空集。传入不存在的 filter_type 同样返回空集。

返回字段

返回 22 个字段 + total_count。主要字段:

字段类型说明
id ~ poster_url漫画基础信息
categoriesjsonbLEFT JOIN categories 整行转 jsonb,包含 idname
lock_statustextVIP 锁定状态
is_finishedboolean是否完结
has_upscaledboolean是否有高清资源
release_datedate发行日期
regiontext地区
authorstext[]作者列表
rating_average / rating_count评分统计
popularity_*integer日/周/月热度
latest_chapter_titletext最新章节标题
latest_chapter_updated_attimestamptz最新章节更新时间
total_countbigint符合筛选条件的总数(count(*) over()),用于分页

排序与分页

固定按 updated_at DESC NULLS LAST, id DESC 排序,通过 p_offset / p_limit 分页。total_count 通过窗口函数附加在每行上,客户端取第一行的值即可用于分页计算。

安全属性

  • SECURITY DEFINER: 否
  • STABLE: 是(同一事务内相同参数返回相同结果)

调用示例

// 按分类筛选,第 2 页
val result = supabase.postgrest
    .rpc("get_comics_by_meta_filter", buildJsonObject {
        put("p_filter_type", "CATEGORY")
        put("p_category_id", 3)
        put("p_offset", 20)
        put("p_limit", 20)
    })
    .decodeList<FilteredComic>()

val totalCount = result.firstOrNull()?.totalCount ?: 0

// 按作者筛选
val byAuthor = supabase.postgrest
    .rpc("get_comics_by_meta_filter", buildJsonObject {
        put("p_filter_type", "AUTHOR")
        put("p_author_name", "尾田栄一郎")
    })
    .decodeList<FilteredComic>()

// 按年份筛选
val by2024 = supabase.postgrest
    .rpc("get_comics_by_meta_filter", buildJsonObject {
        put("p_filter_type", "RELEASE_YEAR")
        put("p_year", "2024")
    })
    .decodeList<FilteredComic>()
// 按连载状态筛选已完结
const { data } = await supabase.rpc('get_comics_by_meta_filter', {
  p_filter_type: 'SERIAL_STATUS',
  p_is_finished: true,
  p_offset: 0,
  p_limit: 20
})

const totalCount = data?.[0]?.total_count ?? 0

count_comics_by_author

统计指定作者的漫画数量(精确匹配 authors 数组,要求 slug IS NOT NULL)。

CREATE FUNCTION count_comics_by_author(p_author_name text)
RETURNS bigint LANGUAGE sql STABLE;
-- 实现
SELECT count(*) FROM comics
WHERE authors @> ARRAY[p_author_name]::text[]
  AND slug IS NOT NULL;
参数类型说明
p_author_nametext作者名,精确匹配
val count = supabase.postgrest
    .rpc("count_comics_by_author", buildJsonObject {
        put("p_author_name", "尾田栄一郎")
    })
    .decodeSingle<Long>()
const { data } = await supabase.rpc('count_comics_by_author', {
  p_author_name: '尾田栄一郎'
})

count_comics_by_category

统计指定分类下的漫画数量(要求 slug IS NOT NULL)。

CREATE FUNCTION count_comics_by_category(p_category_id integer)
RETURNS bigint LANGUAGE sql STABLE;
-- 实现
SELECT count(*) FROM comics
WHERE category_id = p_category_id AND slug IS NOT NULL;
参数类型说明
p_category_idinteger分类 ID
val count = supabase.postgrest
    .rpc("count_comics_by_category", buildJsonObject {
        put("p_category_id", 3)
    })
    .decodeSingle<Long>()
const { data } = await supabase.rpc('count_comics_by_category', {
  p_category_id: 3
})

count_comics_by_tag

统计指定标签关联的漫画数量(查 comic_tags 表)。

CREATE FUNCTION count_comics_by_tag(p_tag_id integer)
RETURNS bigint LANGUAGE sql STABLE;
-- 实现
SELECT count(*) FROM comic_tags WHERE tag_id = p_tag_id;
参数类型说明
p_tag_idinteger标签 ID

三个 count_* 函数均为 STABLE、非 SECURITY DEFINER,受 RLS 约束。count_comics_by_authorcount_comics_by_category 额外要求 slug IS NOT NULL,过滤掉未发布的漫画(slug 在漫画正式上架时生成)。count_comics_by_tag 直接查关联表,不检查 slug。

val count = supabase.postgrest
    .rpc("count_comics_by_tag", buildJsonObject {
        put("p_tag_id", 12)
    })
    .decodeSingle<Long>()
const { data } = await supabase.rpc('count_comics_by_tag', {
  p_tag_id: 12
})

On this page