这是一个阐述如何基于 Supabase、Deno 和 Scaffold-ETH (React) 构建超轻量级 AI 友好的搜索引擎的新系列。
相较于传统的搜索引擎算法,我们使用了更轻量级的方式来构建我们的搜索引擎:
React Frontend - Deno Function - textSearch of Supabase
| Extensions
pgroonga
https://supabase.com/docs/guides/database/full-text-search?queryGroups=language&language=js&queryGroups=example-view&example-view=data#search-using-the-new-column
https://supabase.com/docs/guides/database/extensions/pgroonga?queryGroups=database-method&database-method=dashboard
通过 Dashboard > Database > Extensions
这条路径我们可安装 pgroonga 扩展。
PGroonga 是 Postgres 的一个扩展,它添加了基于 Groonga 的全文搜索索引方法。虽然原生 Postgres 支持全文索引,但仅限于基于字母和数字的语言。PGroonga 提供更广泛的字符支持,使其适用于 Postgres 支持的超集语言,包括日语、中文等。
我们用如下 SQL 命令创建表:
CREATE TABLE "public"."cantonese" (
"id" INT8 NOT NULL,
"data" TEXT NOT NULL,
"note" JSONB,
"category" TEXT,
"created_at" TIMESTAMP WITH TIME ZONE,
PRIMARY KEY ("id")
);
再用如下命令插入测试数据:
INSERT INTO "public"."cantonese" ("id", "data", "note", "category", "created_at") VALUES ('1', '係', '[{"context":{"pron":"hai6","work class":"v"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('2', '咩', '[{"context":{"pron":"me1","work class":"y"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('3', '咪', '[{"context":{"pron":"mai6","work class":"d"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('4', '帶', '[{"context":{"pron":"daai3","work class":"v"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('5', '定', '[{"context":{"pron":"ding6","work class":"d"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('6', '幾', '[{"context":{"pron":"gei2","work class":"m"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('7', '個', '[{"context":{"pron":"go3","work class":"q"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('8', '喼', '[{"context":{"pron":"gip1","work class":"n"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00'), ('9', '去', '[{"context":{"pron":"heoi3","work class":"v"},"contributor":"0x0"}]', 'dict', '2025-03-17 14:00:32.192995+00');
通过 Dashboard > SQL Editor > Create a new snippet
,我们打开 SQL Editor
,来执行 SQL 语句。
执行成功后,我们可以在 Dashboard > Table Editor
中查看到生成的表。
同样是通过 SQL Editor
:
create index [table_name]_data_pgroonga_idx on [table_name] using pgroonga(data);
在执行结束后,我们可以在 Database > Index
中查看到被创建的索引:
SQL Editor
:
select
*
from cantonese_corpus
where data &@~ '定';
🤔 思考题:如何将这个 sql 语句改造成一个 SQL 函数?
💡 Tips:在
Dashboard > Database > Functions
中可以查看到所有函数🤔 思考题 2:
&@~
是什么含义?这两道思考题都可以在评论区留言哦,未来有抽奖~ 🎁
我们在 deno 中进行搜索实现,从而实现超轻量级后端。
https://github.com/NonceGeek/bodhi-searcher/blob/main/deno/bodhi_data_getter.tsx#L361
.get("/text_search_v2", async (context) => {
// 从 url 中读取参数
const queryParams = context.request.url.searchParams;
const key = queryParams.get("keyword");
const tableName = queryParams.get("table_name");
const column = queryParams.get("column");
const limit = parseInt(queryParams.get("limit"), 10); // Get limit from query and convert to integer
const supabase_url = queryParams.get("supabase_url") || Deno.env.get("SUPABASE_URL");
// TODO: make SUPABASE_SERVICE_ROLE_KEY for a spec table as a param.
// 从环境变量中拿到 key
const supabase = createClient(
supabase_url,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
);
console.log("supabase_url", supabase_url);
// 调用 textSearch 函数进行检索
try {
let query = supabase
.from(tableName)
.select("*") // Select all columns initially
.textSearch(column, key)
.order("id", { ascending: false }); // Order results by id_on_chain in descending order
if (!isNaN(limit) && limit > 0) {
query = query.limit(limit); // Apply limit to the query if valid
}
const { data, error } = await query;
// 结果返回
console.log("data", data);
context.response.status = 200;
context.response.body = data;
if (error) {
throw error;
}
} catch (error) {
// 错误处理
console.error("Error fetching data:", error);
context.response.status = 500;
context.response.body = { error: "Failed to fetch data" };
}
})
💡其他语言使用者可以帮助文档中查看到相应语句。
deno run bodhi_data_getter.tsx
我们可以通过 curl
的方式来访问,也可以在浏览器里直接输入 url,需要注意的是,前一种方式下,汉字需要转码。
curl -X GET "http://localhost:8000/text_search_v2?keyword=%E5%AE%9A&table_name=cantonese_corpus_all&column=data&limit=10"
http://localhost:8000/text_search_v2?keyword=%E5%AE%9A&table_name=cantonese_corpus_all&column=data&limit=10
在本地调试成功后,我们通过 deployctl
工具进行部署:
deployctl deploy --prod --project=bodhi-data ./bodhi_data_getter.tsx
然后我们就可以通过线上地址对 api 进行访问了!
https://bodhi-data.deno.dev/text_search_v2?keyword=%E5%AE%9A&table_name=cantonese_corpus_all&column=data&limit=10
┓( ´∀` )┏ 最后是预告!在下一篇中,我们将对描述如何进行前端实现。
【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。