在上一篇文章中,我们通过 Python SDK 实现了 Supabase 数据库的增删改查,在查询、修改和删除数据时,我们使用了类似于 eqin_ 这样的过滤方法,这被称为 过滤器(filters)

supabase-filters.jpg

Supabase 提供了丰富的过滤器,可以满足各种需求,今天我们来详细了解一下 Supabase 的过滤器。

基本用法

下面是 Supabase Python SDK 中的过滤器的基本用法:

response = (
    supabase.table("students")
    .select("*")
    .eq("name", "zhangsan")
    .execute()
)

Supabase 常用的过滤器包括:

过滤器描述示例
eq等于.eq("id", 15)
neq不等于.neq("id", 15)
gt大于.gt("age", 18)
gte大于等于.gte("age", 18)
lt小于.lt("age", 18)
lte小于等于.lte("age", 18)
like模糊匹配.like("name", "zhang%")
ilike模糊匹配,不区分大小写.ilike("name", "zhang%")
is_是否满足某种条件,比如是否为 NULL.is_("name", "null")
not_对某个过滤器取反.not_.is_("name", "null")
in_在列表中.in_("id", [1, 2, 3])

范围列和数组列

在 Supabase 中,范围列用于存储数值范围,这种类型的列可以表示一个区间,例如 [1, 10] 表示从 1 到 10 的范围;数组列用于存储数组,例如 [1, 2, 3] 表示一个数组。我们创建一个示例表,包括范围列和数组列:

CREATE TABLE examples (
    id SERIAL PRIMARY KEY,
    range_column INT4RANGE, -- 范围列
    array_column INT[] -- 数组列
);

并开启 RLS:

ALTER TABLE examples
ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Enable all access"
ON "public"."examples"
FOR ALL
USING (true);

然后插入几条示例数据:

response = (
    supabase.table("examples")
    .insert([
        {"range_column": [1, 5], "array_column": [1, 2, 3, 4, 5]},
        {"range_column": [6, 10], "array_column": [6, 7, 8, 9, 10]},
    ])
    .execute()
)

范围列和数组列支持一些特殊的过滤器,包括:

过滤器描述示例
contains数组中包含所有元素.contains("array_column", ["1", "2", "3"])
contained_by数组中所有元素被包含.contained_by("array_column", ["1", "2", "3", "4", "5", "6"])
range_gt范围大于,所有元素都大于范围内的值.range_gt("range_column", [1, 5])
range_gte范围大于等于,所有元素都大于等于范围内的值.range_gte("range_column", [1, 5])
range_lt范围小于,所有元素都小于范围内的值.range_lt("range_column", [6, 10])
range_lte范围小于等于,所有元素都小于等于范围内的值.range_lte("range_column", [6, 10])
range_adjacent范围相邻且互斥.range_adjacent("range_column", [10, 15])
overlaps数组中含有重叠元素.overlaps("array_column", ["1", "3", "5"])

JSON 列

Supabase 支持 JSON 列,可以存储 JSON 格式的数据,JSON 列有两种类型:

  • JSON - 作为字符串存储
  • JSONB - 作为二进制存储

在几乎所有情况下,推荐使用 JSONB 类型,我们创建一个示例表,包括 JSONB 列:

CREATE TABLE examples2 (
    id SERIAL PRIMARY KEY,
    json_column JSONB
);

和之前一样,开启 RLS:

ALTER TABLE examples2
ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Enable all access"
ON "public"."examples2"
FOR ALL
USING (true);

然后插入几条示例数据:

response = (
    supabase.table("examples2")
    .insert([
        {"json_column": {"name": "zhangsan", "age": 15}},
        {"json_column": {"name": "lisi", "age": 16}},
    ])
    .execute()
)

我们可以在查询时,使用 -> 操作符来获取 JSON 中的某个字段:

response = (
    supabase.table("examples2")
    .select("id, json_column->name, json_column->age")
    .execute()
)

我们也可以在过滤器中使用 -> 操作符:

response = (
    supabase.table("examples2")
    .select("*")
    .eq("json_column->age", 15)
    .execute()
)

如果要过滤的字段值是字符串类型,可以使用 ->> 操作符:

response = (
    supabase.table("examples2")
    .select("*")
    .eq("json_column->>name", "zhangsan")
    .execute()
)

复合过滤器

Supabase 支持复合过滤器,可以将多个过滤器组合在一起,比如:

response = (
    supabase.table("students")
    .select("*")
    .gt("age", 15)
    .lt("age", 18)
    .execute()
)

这个表示 age 大于 15 且小于 18 的数据,如果要表示 age 小于等于 15 或者大于等于 18 的数据,可以使用 or_ 过滤器:

response = (
    supabase.table("students")
    .select("*")
    .or_("age.lte.15,age.gte.18")
    .execute()
)

or_ 过滤器的参数是一个字符串,使用的是原始的 PostgREST 语法,格式为 column.operator.value,多个过滤器之间用逗号分隔。

当我们希望同时匹配多个字段时,可以使用 match 过滤器:

response = (
    supabase.table("students")
    .select("*")
    .match({"age": 15, "name": "zhangsan"})
    .execute()
)

这个表示 age 等于 15 且 name 等于 zhangsan 的数据,match 和多个 eq 是等价的:

response = (
    supabase.table("students")
    .select("*")
    .eq("age", 15)
    .eq("name", "zhangsan")
    .execute()
)