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_type | text | 必填 | 筛选类型,取值见下方 |
p_year | text | NULL | 发行年份,格式 "2024",仅 RELEASE_YEAR 时使用 |
p_is_finished | boolean | NULL | 是否完结,仅 SERIAL_STATUS 时使用 |
p_category_id | bigint | NULL | 分类 ID,仅 CATEGORY 时使用 |
p_author_name | text | NULL | 作者名(精确匹配 authors 数组元素),仅 AUTHOR 时使用 |
p_offset | integer | 0 | 分页偏移,自动 greatest(p_offset, 0) |
p_limit | integer | 20 | 每页条数,自动钳制到 [1, 100] |
p_filter_type 取值
| 值 | 所需参数 | 筛选逻辑 |
|---|---|---|
RELEASE_YEAR | p_year | release_date 落在该年份范围内,年份需匹配 ^\d{4}$ |
SERIAL_STATUS | p_is_finished | is_finished 等于指定值 |
CATEGORY | p_category_id | category_id 等于指定值 |
AUTHOR | p_author_name | authors 数组包含指定作者名(精确匹配,自动 trim) |
p_filter_type 与对应参数不匹配时(如传 CATEGORY 但 p_category_id 为 NULL),WHERE 条件为 false,返回空集。传入不存在的 filter_type 同样返回空集。
返回字段
返回 22 个字段 + total_count。主要字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id ~ poster_url | — | 漫画基础信息 |
categories | jsonb | LEFT JOIN categories 整行转 jsonb,包含 id、name 等 |
lock_status | text | VIP 锁定状态 |
is_finished | boolean | 是否完结 |
has_upscaled | boolean | 是否有高清资源 |
release_date | date | 发行日期 |
region | text | 地区 |
authors | text[] | 作者列表 |
rating_average / rating_count | — | 评分统计 |
popularity_* | integer | 日/周/月热度 |
latest_chapter_title | text | 最新章节标题 |
latest_chapter_updated_at | timestamptz | 最新章节更新时间 |
total_count | bigint | 符合筛选条件的总数(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 ?? 0count_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_name | text | 作者名,精确匹配 |
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_id | integer | 分类 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_id | integer | 标签 ID |
三个 count_* 函数均为 STABLE、非 SECURITY DEFINER,受 RLS 约束。count_comics_by_author 和 count_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
})