教程 / 搜索 / 后端集成 / 在你自己的应用中使用 LingCode Cloud
📝 文字 ● 中级 更新于 2026-06-10

如何在我自己的应用中使用 LingCode Cloud?

一句话:<script src="https://lingcode.dev/sdk/lingcode-v1.js"></script> 加载 SDK,用后端的数据 URL匿名密钥创建一个客户端(两者都可从 lingcode.dev/backends → 你的后端 → 设置 / 连接详情 复制),然后调用 lingcode.from('todos').select().auth.signIn(...).storage 和实时功能。在 /try 里,客户端已经以 window.lingcode 的形式预注入;在你自己的应用中,则需要你亲手接好这两个值。要记住一条规则:数据 API 是表级 CRUD,不是原始 SQL——不支持 JOIN、不支持 upsert,每页 200 行。

如果你在 /try 或 Mac IDE 里构建了应用,后端客户端是直接递给你的——window.lingcode 就那么存在着。可一旦你把这个应用搬到别处——你自己的 Next.js 项目、一个纯 HTML 页面、一个 Vite 构建——你就得亲手把后端接起来。它只是两个值加一个 script 标签,本教程会把整个流程走一遍,包括那条会绊倒从原始 SQL 过来的人的设计约束。

一个 LingCode Cloud 后端就是一个私有 Postgres 数据库(外加认证、存储、实时和向量搜索),你通过 HTTPS 访问它。你不会从浏览器打开数据库连接或运行 SQL——你通过官方客户端 SDK 与一个小型数据网关对话,这个 SDK 的形态类似 Supabase 或 Firebase,所以调用方式让人感到熟悉。下面所有内容都是这个 SDK。

你将学到

你需要的两个值

每个后端都正好有两样客户端需要的东西:

两者都能在 lingcode.dev/backends 找到——打开你的后端,从设置里复制连接详情(和你粘贴到其他 MCP 客户端里的是同一对)。在框架中,把它们存为公开配置——对于 Next.js,是 NEXT_PUBLIC_LINGCODE_BACKEND_URLNEXT_PUBLIC_LINGCODE_BACKEND_ANON_KEY;对于打包工具,就按你的 import.meta.env / process.env 约定来。它们是公开的,所以应该放在客户端配置里,而不是只在服务端可见的密钥里。

匿名密钥 vs. 私密密钥:匿名密钥按设计就是公开的。你的私密密钥(Stripe 私密密钥、第三方 API 密钥)绝不能进浏览器——把它们放进后端的 Secrets,并通过函数lingcode.functions.invoke(...))来使用,函数在服务端运行。任何客户端能看到的东西,都当作公开内容来对待。

加载 SDK 并创建客户端

SDK 是从 CDN 提供的单个零依赖文件。纯 HTML 版本:

<script src="https://lingcode.dev/sdk/lingcode-v1.js"></script>
<script>
  const lingcode = LingCode.createClient(
    'https://lingcode.dev/api/cloud/be/<your-backend-id>',
    '<your-anon-key>'
  );
</script>

在模块/打包工具的应用中,加载同一个文件,并用你的环境变量值调用 LingCode.createClient(url, key)。(在 /try 和 Mac 预览里你完全跳过这一步——客户端已经以 window.lingcode 的形式存在,预先接好了那个项目的后端。绝不要在那里重新创建它或硬编码密钥。)

在读取认证状态之前,先等客户端在加载时稳定一次——它会先把任何登录重定向处理完:

await lingcode.ready;
const user = lingcode.auth.getUser(); // { id, email } | null

读写数据

每次调用都返回 { data, error }——使用 data 之前先检查 error。过滤器链接在动词之前:

// 读取
const { data, error } = await lingcode
  .from('todos')
  .eq('done', false)
  .order('created_at', { ascending: false })
  .limit(50)
  .select();

// 写入
await lingcode.from('todos').insert({ title: 'Buy milk' });
await lingcode.from('todos').eq('id', 1).update({ done: true });  // 必须有过滤器
await lingcode.from('todos').eq('id', 1).delete();                // 必须有过滤器

过滤运算符:.eq .neq .gt .gte .lt .lte .like .ilike .in(col,[…]) .is(col,null),以及一次性多个等值匹配的 .match({a:1,b:2})。多个过滤器以 AND 连接。updatedelete 在没有过滤器时拒绝执行,所以你不会意外清空一张表。

认证、存储、实时、向量

必须知道的一件事:它是表级 CRUD,不是原始 SQL

这是会让从 SQL 客户端或 PostgREST 过来的人意外的约束,也是"代码一次就跑通"和"代码报 400"之间的分水岭。运行时数据 API 一次只操作一张表。所以:

任何真正涉及关系或较重的操作——跨表报表、索引、约束、生成列、种子数据——都属于 schema,而不是运行时调用。创建一个 VIEW(然后像查表一样从中 select())、添加索引,或者从控制台的 SQL 标签页或 apply_migration 工具运行迁移。网关被有意保持为一个轻薄、安全的 CRUD 层;Postgres 的全部能力就在下面一层,在你的迁移里。

从 Supabase 迁移?

SDK 有意做成形态类似 Supabase,所以大多数调用点都能一一对应。对不上的只有上面那两条规则:把 .select('*, author(*)') 的 JOIN 改写为分别取数据,把 .upsert() 改写为先 insert 再 update。在 Mac IDE 或 /try 里,只需让 agent "把我的 Supabase 项目迁移到 LingCode 并部署"——迁移技能会替你处理 schema、数据以及这些改写。

下一步