16个版本
0.2.6 | 2023年6月11日 |
---|---|
0.2.5 | 2023年6月6日 |
0.2.4 | 2023年5月29日 |
0.1.9 | 2023年5月21日 |
#371 in 解析器实现
用于 flinch
195KB
4.5K SLoC
FLQL - Flinch查询语言
FLQL - Flinch查询语言是一种轻量级的查询语言,用于从称为Flinch的内存数据库中检索数据。Flinch是一种实时非结构化文档数据库,能够以JSON格式存储和检索文档。
FLQL是为了简化Flinch中的查询过程而创建的,使开发者更容易从数据库中检索数据。它是一种简单、直观、易于学习的语言。
功能
- FLQL支持基本的CRUD(创建、读取、更新、删除)操作。
- 它支持基于多种标准查询文档,包括文本匹配、日期范围和数值范围。
- 它使用简单直观的语法,易于阅读和编写。
- FLQL针对性能进行了优化,可以轻松处理大型数据集。
入门
要使用FLQL,您需要在系统上安装并运行Flinch。一旦Flinch启动并运行,您就可以开始使用FLQL查询您的数据。
//Create collection
new({});
// TTL
ttl(60).if('').into('');
//Drop collection
drop('');
//Check if pointer exists in collection
exists('').into('');
//Length of collection
length('');
//Update or Insert into collection
put({}).into('');
//Conditional Update or Insert into collection
put({}).when('gjson_expression').into('');
//Update or Insert into collection to a Pointer
put({}).pointer('').into('');
//Get from collection
get.from('');
//Conditional Get from collection
get.when('gjson_expression').from('');
//Get Pointer from collection
get.pointer('').from('');
//Get View from collection
get.view('').from('');
//Get Clip from collection
get.clip('').from('');
//Delete from collection
delete.from('');
//Conditional Delete from collection
delete.when('gjson_expression').from('');
//Delete Pointer from collection
delete.pointer('').from('');
//Delete View from collection
delete.view('').from('');
//Delete Clip from collection
delete.clip('').from('');
示例
use flql::{parse, Flql};
let commands = vec![
"new({});",
"drop('');",
"exists('').into('');",
"length('');",
"put({}).into('');",
"put({}).when('gjson_expression').into('');",
"put({}).pointer('').into('');",
"get.from('');",
"get.when('gjson_expression').from('');",
"get.pointer('').from('');",
"get.view('').from('');",
"get.clip('').from('');",
"delete.from('');",
"delete.when('gjson_expression').from('');",
"delete.pointer('').from('');",
"delete.clip('').from('');"
];
for command in commands {
let chk = parse(command);
assert!(chk.is_ok(),"{:?}",chk.err());
if chk.is_ok() {
let parsed = chk.unwrap();
match parsed {
Flql::New(_) => {}
Flql::Drop(_) => {}
Flql::Exists(_,_) => {}
Flql::Length(_) => {}
Flql::Flush(_) => {}
Flql::Put(_, _) => {}
Flql::PutWhen(_, _, _) => {}
Flql::PutPointer(_, _, _) => {}
Flql::Search(_,_) => {}
Flql::Get(_) => {}
Flql::GetWhen(_, _) => {}
Flql::GetPointer(_, _) => {}
Flql::GetView(_, _) => {}
Flql::GetClip(_, _) => {}
Flql::GetIndex(_,_) => {}
Flql::GetRange(_,_,_,_) => {}
Flql::Delete(_) => {}
Flql::DeleteWhen(_, _) => {}
Flql::DeletePointer(_, _) => {}
Flql::DeleteClip(_, _) => {}
Flql::None => {}
}
}
}
在when
函数中,您可以使用来自(https://github.com/tidwall/gjson.rs)的任何表达式来操作数据。
文档来自gjson仓库:本文件旨在通过示例说明GJSON路径的结构。
最终的实现是 github.com/tidwall/gjson。
使用GJSON Playground在线尝试语法。
路径结构
一个GJSON路径被设计成一系列通过点字符.
分隔的组件。
除了点字符外,还有一些具有特殊意义的字符,包括|
、#
、@
、\
、*
、!
和?
。
示例
给定以下JSON
{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
]
}
以下GJSON路径计算出的值如下。
基本
在许多情况下,您只需通过对象名称或数组索引来检索值。
name.last "Anderson"
name.first "Tom"
age 37
children ["Sara","Alex","Jack"]
children.0 "Sara"
children.1 "Alex"
friends.1 {"first": "Roger", "last": "Craig", "age": 68}
friends.1.first "Roger"
通配符
键可能包含特殊通配符字符 *
和 ?
。 *
将匹配任意零个或多个字符,而 ?
则匹配任意单个字符。
child*.2 "Jack"
c?ildren.0 "Sara"
转义字符
特殊目的字符,如 .
、*
和 ?
可以使用 \
转义。
fav\.movie "Deer Hunter"
数组
#
字符允许深入到 JSON 数组。
要获取数组的长度,只需单独使用 #
即可。
friends.# 3
friends.#.age [44,68,47]
查询
您也可以使用 #(...)
来查询数组中的第一个匹配项,或者使用 #(...)#
来查找所有匹配项。查询支持 ==
、!=
、<
、<=
、>
、>=
比较运算符,以及简单的模式匹配运算符 %(像)和
!%(不像是)。
friends.#(last=="Murphy").first "Dale"
friends.#(last=="Murphy")#.first ["Dale","Jane"]
friends.#(age>45)#.last ["Craig","Murphy"]
friends.#(first%"D*").last "Murphy"
friends.#(first!%"D*").last "Craig"
要查询数组中的非对象值,可以省略操作符右侧的字符串。
children.#(!%"*a*") "Alex"
children.#(%"*a*")# ["Sara","Jack"]
允许嵌套查询。
friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
请注意,在 v1.3.0 之前,查询使用了 #[...]
方括号。这在 v1.3.0 中发生了变化,以避免与新的 多路径 语法混淆。为了向后兼容,#[...]
将继续在下一个主要版本中工作。
~
(波浪号)运算符将在比较之前将值转换为布尔值。
例如,使用以下 JSON
{
"vals": [
{ "a": 1, "b": true },
{ "a": 2, "b": true },
{ "a": 3, "b": false },
{ "a": 4, "b": "0" },
{ "a": 5, "b": 0 },
{ "a": 6, "b": "1" },
{ "a": 7, "b": 1 },
{ "a": 8, "b": "true" },
{ "a": 9, "b": false },
{ "a": 10, "b": null },
{ "a": 11 }
]
}
您现在可以查询所有真(或似真)或假(或似假)的值
vals.#(b==~true)#.a >> [1,2,6,7,8]
vals.#(b==~false)#.a >> [3,4,5,9,10,11]
最后一个不存在的值被视为 false
点与管道
.
是标准分隔符,但也可以使用 |
。在大多数情况下,它们都返回相同的结果。当 |
与 .
不同时,是在 #
后用于 数组 和 查询 的情况下。
这里有一些例子
friends.0.first "Dale"
friends|0.first "Dale"
friends.0|first "Dale"
friends|0|first "Dale"
friends|# 3
friends.# 3
friends.#(last="Murphy")# [{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
friends.#(last="Murphy")#.first ["Dale","Jane"]
friends.#(last="Murphy")#|first <non-existent>
friends.#(last="Murphy")#.0 []
friends.#(last="Murphy")#|0 {"first": "Dale", "last": "Murphy", "age": 44}
friends.#(last="Murphy")#.# []
friends.#(last="Murphy")#|# 2
让我们分析其中的一些。
路径 friends.#(last="Murphy")#
独自使用的结果是
[{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
.first
后缀将在返回结果之前处理每个数组元素上的 first
路径。这变成
["Dale","Jane"]
但 |first
后缀实际上是在之前的结果之后处理 first
路径。由于前一个结果是一个数组而不是一个对象,因此无法处理,因为 first
不存在。
然而,|0
后缀返回
{"first": "Dale", "last": "Murphy", "age": 44}
因为 0
是先前结果的第一索引。
修饰符
修饰符是在 JSON 上执行自定义处理的路径组件。
例如,在上述 JSON 负载中使用内置的 @reverse
修饰符将反转 children
数组
children.@reverse ["Jack","Alex","Sara"]
children.@reverse.0 "Jack"
目前有以下内置修饰符
@reverse
:反转数组或对象的成员。@ugly
:从 JSON 中删除所有空白。@pretty
:使 JSON 更易于阅读。@this
:返回当前元素。它可以用来检索根元素。@valid
:确保 JSON 文档有效。@flatten
:扁平化数组。@join
:将多个对象连接成一个对象。@keys
:返回对象的键数组。@values
:返回对象的值数组。@tostr
:将 JSON 转换为字符串。包装 JSON 字符串。@fromstr
:将字符串转换为 JSON。解包 JSON 字符串。@group
:分组对象数组。参见 e4fc67c。
修饰符参数
修饰符可以接受一个可选参数。该参数可以是有效的 JSON 负载或只是字符。
例如,@pretty
修饰符接受一个 JSON 对象作为其参数。
@pretty:{"sortKeys":true}
这使得 JSON 更易于阅读并排序所有键。
{
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"age": 44, "first": "Dale", "last": "Murphy"},
{"age": 68, "first": "Roger", "last": "Craig"},
{"age": 47, "first": "Jane", "last": "Murphy"}
],
"name": {"first": "Tom", "last": "Anderson"}
}
@pretty
的完整选项列表为 sortKeys
、indent
、prefix
和 width
。请参阅 格式化选项 获取更多信息。
多路径
从 v1.3.0 版本开始,GJSON 添加了将多个路径合并在一起以形成新文档的功能。用方括号 [...]
或花括号 {...}
括起来的逗号分隔的路径将分别生成一个新数组或对象。
例如,使用给定的多路径
{name.first,age,"the_murphys":friends.#(last="Murphy")#.first}
这里我们选择了名字、年龄以及姓氏为 "Murphy" 的朋友的名字。
您会注意到可以提供一个可选键,在这种情况下是 "the_murphys",以强制将键分配给值。否则,将使用实际字段的名称,在这种情况下是 "first"。如果无法确定名称,则使用 "_"。
这导致
{"first":"Tom","age":37,"the_murphys":["Dale","Jane"]}
字面量
从 v1.12.0 版本开始,GJSON 添加了对 JSON 文字的支持,这提供了一种构建静态 JSON 块的方法。这当使用 多路径 构建新的 JSON 文档时特别有用。
JSON 文字以感叹号声明字符开头。
例如,使用给定的多路径
{name.first,age,"company":!"Happysoft","employed":!true}
这里我们选择了名字和年龄。然后添加了两个新字段,"company" 和 "employed"。
这导致
{"first":"Tom","age":37,"company":"Happysoft","employed":true}
致谢
没有以下内容,这个库将无法实现
KSQL https://crates.io/crates/ksql
gjson.rs https://github.com/tidwall/gjson.rs
使用库中代码的目的(而不是作为库使用)是添加额外功能并移除不必要的功能。
依赖项
~6MB
~110K SLoC