sqlite-lines 作者 asg017

星标

README 源代码

sqlite-lines

sqlite-lines 是一个 SQLite 扩展,用于从文件或 blob 中读取行。

Benchmark between sqlite-lines and various other data processing tools

更多信息请参见基准测试

用法

.load ./lines0
select line from lines_read('logs.txt');

当与 SQLite 的 JSON 支持结合使用时,sqlite-lines 对于面向行的数据集(如 ndjsonJSON Lines)非常有用。在这里,我们计算 Google 的 Quick, Draw! 数据集中针对 calendars.ndjson 的前 5 个国家/地区参与者。

select
  line ->> '$.countrycode' as countrycode,
  count(*)
from lines_read('./calendar.ndjson')
group by 1
order by 2 desc
limit 5;
/*
┌─────────────┬──────────┐
│ countrycode │ count(*) │
├─────────────┼──────────┤
│ US          │ 141001   │
│ GB          │ 22560    │
│ CA          │ 11759    │
│ RU          │ 9250     │
│ DE          │ 8748     │
└─────────────┴──────────┘
*/

使用 SQLite CLI 的 fsdir() 表函数和 lines_read() 从目录中的每个文件中读取行。

select
  name as file,
  lines.rowid as line_number,
  line
from fsdir('logs')
join lines_read(name) as lines
where name like '%.txt';
/*
┌─────────────────────┬──────┐
│ file  │ line_number | line │
├───────┼─────────────┤──────┤
| a.txt | 1           | x    |
| a.txt | 2           | y    |
| a.txt | 3           | z    |
| b.txt | 1           | xx   |
| b.txt | 2           | yy   |
| c.txt | 1           | xxx  |
└───────┴─────────────┴──────┘
*/

文档

完整的 API 参考和详细文档请参见 docs.md

安装

语言 安装
Python pip install sqlite-lines PyPI
Datasette datasette install datasette-sqlite-lines Datasette
Node.js npm install sqlite-lines npm
Deno deno.land/x/sqlite_lines deno.land/x release
Ruby gem install sqlite-lines Gem
Github 发布版本 GitHub tag (latest SemVer pre-release)

发布页面包含适用于 Linux amd64 和 MacOS (amd64, 无 arm) 的预构建二进制文件。

作为可加载扩展

如果您想将 sqlite-lines 用作运行时可加载扩展,请从发布版本中下载 lines0.dylib (适用于 MacOS) 或 lines0.so 文件,并将其加载到您的 SQLite 环境中。

注意:文件名中的 0 (lines0.dyliblines0.so) 表示 sqlite-lines 的主要版本。目前 sqlite-lines 处于 v1 之前,因此未来版本可能会有重大变更。

例如,如果您正在使用 SQLite CLI,可以这样加载库

.load ./lines0
select lines_version();
-- v0.0.1

或者在 Python 中,使用内置的 sqlite3 模块

import sqlite3

con = sqlite3.connect(":memory:")

con.enable_load_extension(True)
con.load_extension("./lines0")

print(con.execute("select lines_version()").fetchone())
# ('v0.0.1',)

或者在 Node.js 中使用 better-sqlite3

const Database = require("better-sqlite3");
const db = new Database(":memory:");

db.loadExtension("./lines0");

console.log(db.prepare("select lines_version()").get());
// { 'lines_version()': 'v0.0.1' }

或者与 Datasette 一起使用(使用“无文件系统”版本来限制安全漏洞)

datasette data.db --load-extension ./lines_nofs0

Windows 尚不支持 - 尚未

在浏览器中使用 WASM/JavaScript

sqlite-lines 也作为一个独立的 SQL.js 库发布。它本质上是原始 SQL.js 库的一个分支,增加了 lines_version()lines()sqlite-lines 函数。

请查看此 Observable notebook 以获取完整演示。 发布页面包含 JavaScript 和 WASM 文件。

sqlite-lines CLI

sqlite-lines 带有一个模仿 ndjson-cli 的示例 CLI,用于演示 sqlite-lines 的速度和多功能性。您可以从发布页面下载预编译版本,或者自己构建,使用

make cli
./dist/sqlite-lines

sqlite-lines CLI 从标准输入读取数据,并通过其参数使用 SQL 代码应用转换。

第一个参数应该是用于转换来自标准输入的单行的 SQL 表达式。可用列包括 rowid(正在处理的“行号”)和 dline 的别名,表示当前行的文本内容,灵感来自 ndjson-cli)。例如,要使用 upper() 将文件中的每一行转换为大写,使用

$ cat names.txt | sqlite-lines 'rowid || upper(d)'
1ALEX
2BRIAN
3CRAIG

这包括 SQLite 用于 NDJSON/JSONL 文件的新的 JSON ->->> 运算符

> "$.name", "age": d ->> "$.stats.age")'">
$ cat data.ndjson | sqlite-lines 'd ->> "$.id"'
$ cat data.ndjson | sqlite-lines 'json_object("name", d ->> "$.name", "age": d ->> "$.stats.age")'

第二个参数是另一个 SQL 表达式,用于底层 SQL 查询的 WHERE 语句中,以过滤掉行。

> "$.age" > 40'">
# get the names of all people older than 40
cat data.ndjson | sqlite-lines 'd ->> "$.name"' 'd ->> "$.age" > 40'

第三个参数是另一个 SQL 表达式,用于底层 SQL 查询的 GROUP BY 语句中,以聚合行。

关于 CSV 解析的注意事项

sqlite-lines 对于 CSV 文件来说不是一个好的选择。技术上可行,但一旦您的数据在字段或标题中包含 \n 字符,您就会得到损坏的结果。

相反,您应该使用“官方”的 CSV 虚拟表,或在 SQLite CLI 中使用 .import 命令。