FQL语法基础 #
一、FQL概述 #
1.1 什么是FQL #
FQL(Fauna Query Language)是FaunaDB的原生查询语言,采用函数式编程风格。
text
FQL特点:
├── 函数式编程风格
├── 表达式组合
├── 类型安全
├── 丰富的内置函数
├── 支持用户定义函数
└── 支持事务
1.2 FQL vs SQL #
| 特性 | FQL | SQL |
|---|---|---|
| 风格 | 函数式 | 声明式 |
| 组合 | 嵌套表达式 | 子查询 |
| 类型 | 动态类型 | 静态类型 |
| 事务 | 原生支持 | 需要显式声明 |
二、基本语法 #
2.1 表达式 #
FQL由表达式组成,每个表达式返回一个值。
javascript
// 简单表达式
"Hello World" // 字符串
123 // 数字
true // 布尔值
null // 空值
// 复合表达式
Add(1, 2, 3) // 返回 6
Concat(["a", "b"]) // 返回 "ab"
2.2 函数调用 #
javascript
// 基本函数调用
FunctionName(arg1, arg2, ...)
// 示例
Add(1, 2)
Concat("Hello", " ", "World")
Lower("HELLO")
2.3 嵌套表达式 #
javascript
// 表达式嵌套
Add(Multiply(2, 3), 4) // 2*3 + 4 = 10
// 查询嵌套
Get(
Ref(
Collection("users"),
"123456"
)
)
三、数据类型 #
3.1 标量类型 #
javascript
// 字符串
"Hello World"
'Hello World'
// 数字
42
3.14
-100
// 布尔
true
false
// 空值
null
3.2 集合类型 #
javascript
// 数组
[1, 2, 3, 4, 5]
["a", "b", "c"]
[{ name: "Tom" }, { name: "Jerry" }]
// 对象
{
name: "Tom",
age: 30,
active: true
}
3.3 特殊类型 #
javascript
// 引用
Ref(Collection("users"), "123456")
// 时间戳
Time("2024-01-01T00:00:00Z")
Now()
// 日期
Date("2024-01-01")
// 数据库引用
Database("my_database")
// 集合引用
Collection("users")
// 索引引用
Index("users_by_email")
四、常用函数 #
4.1 数学函数 #
javascript
// 加法
Add(1, 2, 3) // 6
// 减法
Subtract(10, 3) // 7
// 乘法
Multiply(2, 3, 4) // 24
// 除法
Divide(10, 2) // 5
// 取模
Modulo(10, 3) // 1
// 绝对值
Abs(-5) // 5
// 最大/最小值
Max(1, 5, 3, 2) // 5
Min(1, 5, 3, 2) // 1
// 四舍五入
Round(3.14159, 2) // 3.14
// 向上/向下取整
Ceil(3.2) // 4
Floor(3.8) // 3
4.2 字符串函数 #
javascript
// 连接
Concat(["Hello", " ", "World"]) // "Hello World"
// 转换大小写
Upper("hello") // "HELLO"
Lower("HELLO") // "hello"
// 字符串长度
Length("Hello") // 5
// 子字符串
Substring("Hello World", 0, 5) // "Hello"
// 替换
ReplaceStr("Hello World", "World", "Fauna") // "Hello Fauna"
// 正则匹配
Regex("Hello123", "[0-9]+") // true
// 分割
Split("a,b,c", ",") // ["a", "b", "c"]
// 去除空白
Trim(" Hello ") // "Hello"
// 字符串格式化
Format("Hello %s, you are %d years old", "Tom", 30)
// "Hello Tom, you are 30 years old"
4.3 数组函数 #
javascript
// 数组长度
Count([1, 2, 3, 4, 5]) // 5
// 是否包含
ContainsValue([1, 2, 3], 2) // true
// 数组连接
Append([1, 2], [3, 4]) // [1, 2, 3, 4]
// 数组前置
Prepend([1, 2], [3, 4]) // [1, 2, 3, 4]
// 获取元素
Select(0, ["a", "b", "c"]) // "a"
// 过滤
Filter(
[1, 2, 3, 4, 5],
Lambda("x", GT(Var("x"), 2))
) // [3, 4, 5]
// 映射
Map(
[1, 2, 3],
Lambda("x", Multiply(Var("x"), 2))
) // [2, 4, 6]
// 归约
Reduce(
[1, 2, 3, 4, 5],
Lambda((acc, val) => Add(acc, val)),
0
) // 15
4.4 对象函数 #
javascript
// 合并对象
Merge(
{ a: 1, b: 2 },
{ b: 3, c: 4 }
) // { a: 1, b: 3, c: 4 }
// 选择属性
Select(["name"], { name: "Tom", age: 30 }) // "Tom"
// 检查属性存在
ContainsPath({ a: { b: 1 } }, ["a", "b"]) // true
// 获取所有键
Keys({ a: 1, b: 2, c: 3 }) // ["a", "b", "c"]
// 获取所有值
Values({ a: 1, b: 2, c: 3 }) // [1, 2, 3]
五、逻辑控制 #
5.1 条件表达式 #
javascript
// If表达式
If(
GT(5, 3),
"greater",
"not greater"
) // "greater"
// 嵌套条件
If(
LT(age, 18),
"minor",
If(
LT(age, 65),
"adult",
"senior"
)
)
5.2 逻辑运算 #
javascript
// 与
And(true, true, false) // false
// 或
Or(false, false, true) // true
// 非
Not(true) // false
// 组合使用
And(
GT(age, 18),
LT(age, 65),
Equals(status, "active")
)
5.3 比较运算 #
javascript
// 相等
Equals("a", "a") // true
// 不等
Not(Equals("a", "b")) // true
// 大于/小于
GT(5, 3) // true
GTE(5, 5) // true
LT(3, 5) // true
LTE(5, 5) // true
六、Lambda表达式 #
6.1 Lambda语法 #
javascript
// 基本语法
Lambda("param", expression)
// 多参数
Lambda(
["param1", "param2"],
expression
)
// 解构参数
Lambda(
{ name: "name", age: "age" },
expression
)
6.2 Lambda使用 #
javascript
// 在Map中使用
Map(
[1, 2, 3, 4, 5],
Lambda("x", Multiply(Var("x"), 2))
)
// 结果: [2, 4, 6, 8, 10]
// 在Filter中使用
Filter(
[1, 2, 3, 4, 5],
Lambda("x", GT(Var("x"), 2))
)
// 结果: [3, 4, 5]
// 多参数Lambda
Map(
[[1, 2], [3, 4], [5, 6]],
Lambda(
["a", "b"],
Add(Var("a"), Var("b"))
)
)
// 结果: [3, 7, 11]
6.3 Var函数 #
javascript
// 使用Var获取Lambda参数
Lambda("x", Var("x")) // 返回参数x的值
// 嵌套使用
Lambda("x",
Lambda("y",
Add(Var("x"), Var("y"))
)
)
七、Let绑定 #
7.1 基本语法 #
javascript
// Let绑定变量
Let(
{
x: 10,
y: 20
},
Add(Var("x"), Var("y"))
) // 30
7.2 链式绑定 #
javascript
// 变量依赖
Let(
{
a: 10,
b: Add(Var("a"), 5), // b = 15
c: Multiply(Var("b"), 2) // c = 30
},
Var("c")
) // 30
7.3 实际应用 #
javascript
// 复杂查询中使用Let
Let(
{
user: Get(Ref(Collection("users"), "123456")),
orders: Paginate(
Match(Index("orders_by_user"), Select(["ref"], Var("user")))
)
},
{
user: Var("user"),
orderCount: Count(Var("orders"))
}
)
八、Do表达式 #
8.1 基本用法 #
javascript
// Do执行多个操作,返回最后一个
Do(
Create(Collection("logs"), { data: { action: "create_user" } }),
Create(Collection("users"), { data: { name: "Tom" } })
)
// 返回创建的用户文档
8.2 实际应用 #
javascript
// 创建用户并记录日志
Do(
Create(Collection("users"), {
data: { name: "Tom", email: "tom@example.com" }
}),
Create(Collection("audit_logs"), {
data: {
action: "user_created",
timestamp: Now()
}
})
)
九、错误处理 #
9.1 Abort #
javascript
// Abort中止事务
If(
LT(balance, amount),
Abort("Insufficient balance"),
Do(
Update(userRef, { data: { balance: Subtract(balance, amount) } }),
Create(Collection("transactions"), { data: { amount: amount } })
)
)
9.2 错误处理模式 #
javascript
// 检查文档是否存在
Let(
{
doc: If(
Exists(Ref(Collection("users"), "123456")),
Get(Ref(Collection("users"), "123456")),
null
)
},
If(
Equals(Var("doc"), null),
{ error: "Document not found" },
Var("doc")
)
)
十、分页 #
10.1 Paginate #
javascript
// 基本分页
Paginate(Match(Index("all_users")))
// 设置大小
Paginate(
Match(Index("all_users")),
{ size: 10 }
)
// 设置游标
Paginate(
Match(Index("all_users")),
{
size: 10,
after: Ref(Collection("users"), "123456")
}
)
// 反向分页
Paginate(
Match(Index("all_users")),
{
size: 10,
before: Ref(Collection("users"), "654321")
}
)
10.2 分页结果 #
javascript
// 分页返回格式
{
data: [...],
after: ..., // 下一页游标
before: ... // 上一页游标
}
十一、命名规范 #
11.1 集合命名 #
text
集合命名规范:
├── 使用小写字母
├── 使用下划线分隔
├── 使用复数形式
└── 示例:users, products, order_items
11.2 索引命名 #
text
索引命名规范:
├── 描述性名称
├── 包含查询字段
├── 使用下划线分隔
└── 示例:users_by_email, products_by_category
11.3 函数命名 #
text
函数命名规范:
├── 使用动词开头
├── 描述功能
├── 使用下划线分隔
└── 示例:create_user, get_user_orders
十二、最佳实践 #
12.1 代码组织 #
javascript
// 使用Let组织复杂查询
Let(
{
// 步骤1:获取用户
user: Get(userRef),
// 步骤2:获取用户订单
orders: Paginate(
Match(Index("orders_by_user"), Select(["ref"], Var("user"))),
{ size: 10 }
),
// 步骤3:计算统计
stats: {
totalOrders: Count(Var("orders")),
userStatus: Select(["data", "status"], Var("user"))
}
},
// 返回结果
{
user: Var("user"),
orders: Var("orders"),
stats: Var("stats")
}
)
12.2 性能优化 #
javascript
// 避免N+1查询
Let(
{
users: Paginate(Match(Index("all_users")), { size: 100 }),
enrichedUsers: Map(
Var("users"),
Lambda("userRef",
Let(
{
user: Get(Var("userRef")),
orderCount: Count(
Match(Index("orders_by_user"), Var("userRef"))
)
},
Merge(Var("user"), { orderCount: Var("orderCount") })
)
)
)
},
Var("enrichedUsers")
)
十三、总结 #
FQL语法要点:
| 特性 | 说明 |
|---|---|
| 表达式 | 一切皆表达式 |
| 函数 | 丰富的内置函数 |
| Lambda | 匿名函数 |
| Let | 变量绑定 |
| Do | 顺序执行 |
| If | 条件判断 |
下一步,让我们学习数据类型!
最后更新:2026-03-27