18

如果我有一些示例数据,如何将其放入 SQLite(最好是完全自动化的)?

{"uri":"/","user_agent":"example1"}
{"uri":"/foobar","user_agent":"example1"}
{"uri":"/","user_agent":"example2"}
{"uri":"/foobar","user_agent":"example3"}
4

4 回答 4

27

我发现最简单的方法是使用jq和 CSV 作为中间格式。

编辑:正如所指出的(感谢@Leo),最初的问题确实显示了换行符分隔的 JSON 对象,每个对象本身都符合rfc4627,但并非全部都以这种格式。 jq可以处理单个 JSON 对象数组,但使用jq '.[]' <input.json >preprocessed.json. 如果您碰巧正在处理 JSON 文本序列 ( rfc7464 ),幸运的是jq也得到了您的支持--seq

编辑 2:换行符分隔的 JSON 和 JSON 文本序列都有一个重要的优势;它们将内存需求降低到 O(1),这意味着您的总内存需求仅取决于您最长的输入行,而将整个输入放在一个数组中要求您的解析器可以处理后期错误(即在前 100k 之后元素存在语法错误),据我所知,这通常不是这种情况,或者它必须解析整个文件两次(首先验证语法,然后解析,在这个过程中丢弃以前的元素,就像jq --stream) 这在我的知识中也很少发生,或者它会尝试一次解析整个输入并在一步中返回结果(想想接收一个 Python 字典,其中包含你说的全部 50G 输入数据加上开销),这通常是内存支持,因此将您的内存占用量增加了大约您的总数据大小。

编辑 3:如果您遇到任何障碍,请尝试使用keys_unsorted而不是keys。我自己没有测试过(我有点假设我的列已经排序),但是@Kyle Barron报告说这是需要的。

获取 CSV

首先将数据写入文件。我将在这里假设data.json

然后使用构造标题jq

% head -1 data.json | jq -r 'keys | @csv'
"uri","user_agent"

head -1是因为我们只想要一条线。 jq's-r使输出成为纯字符串,而不是包装 CSV 的 JSON 字符串。然后我们调用内部函数keys将输入的键作为数组获取。我们将其发送到@csv格式化程序,该格式化程序向我们输出一个带有引号的 CSV 格式标题的字符串。

然后我们需要构建数据。

% jq -r '[.[]] | @csv' < data.json
"/","example1"
"/foobar","example1"
"/","example2"
"/foobar","example3"

我们现在获取整个输入并使用解构关联数组(映射).[],然后将其放回一个简单的数组[…]中。这基本上将我们的字典转换为键数组。发送到@csv格式化程序,我们再次得到一些 CSV。

把它们放在一起,我们得到一个单一的形式:

% (head -1 data.json | jq -r 'keys | @csv' && jq -r '[.[]] | @csv' < data.json) > data.csv

如果您需要即时转换数据,即没有文件,请尝试以下操作:

% cat data.json | (read -r first && jq -r '(keys | @csv),( [.[]] | @csv)' <<<"${first}" && jq -r '[.[]] | @csv')

将其加载到 SQLite

打开一个 SQLite 数据库:

sqlite3 somedb.sqlite

现在在交互式 shell 中执行以下操作(假设您将 CSV 写入data.csv并希望将其放在名为 的表中my_table):

.mode csv
.import data.csv my_table

现在关闭外壳并再次打开它以获得干净的环境。您现在可以轻松地SELECT从数据库中做任何您想做的事情。

把它们放在一起

在那里进行asciinema记录:

asciiccast

于 2017-09-25T14:32:18.703 回答
17

在没有 CSV 或第 3 方工具的情况下执行此操作的一种方法是使用SQLite 的扩展与 CLI 工具中提供的JSON1扩展相结合readfilesqlite3

如果输入文件是格式良好的 JSON 文件,例如以数组形式给出的示例:

[
{"uri":"/","user_agent":"example1"},
{"uri":"/foobar","user_agent":"example1"},
{"uri":"/","user_agent":"example2"},
{"uri":"/foobar","user_agent":"example3"}
]

然后可以将其读入相应的my_table表中,如下所示。my_db.db使用 sqlite3 CLI打开 SQLite 数据库文件:

sqlite3 my_db.db

然后my_table使用创建:

CREATE TABLE my_table(uri TEXT, user_agent TEXT);

最后,my_data.json可以使用 CLI 命令将其中的 JSON 数据插入到表中:

INSERT INTO my_table SELECT 
  json_extract(value, '$.uri'), 
  json_extract(value, '$.user_agent')
FROM json_each(readfile('my_data.json'));

除了总体上是一个“更直接”的解决方案外,这还具有比 CSV 更一致地处理 JSON NULL 值的优势,否则会将它们作为空字符串导入。

如果初始 JSON 文件是换行符分隔的 JSON 元素,则可以首先使用以下方法进行转换jq

jq -s <my_data_raw.json >my_data.json

jq可能有一种方法可以使用 JSON1 直接在 SQLite 中执行此操作,但鉴于我已经在导入 SQLite 之前已经使用过处理数据,因此我没有追求这一点。

于 2020-06-27T06:25:02.483 回答
6

sqlitebiter 似乎提供了一个 python 解决方案:

将 CSV/Excel/HTML/JSON/LTSV/Markdown/SQLite/TSV/Google-Sheets 转换为 SQLite 数据库文件的 CLI 工具。http://sqlitebiter.rtfd.io/

文档: http ://sqlitebiter.readthedocs.io/en/latest/

项目: https ://github.com/thombashi/sqlitebiter

  • 最后一次更新大约 3 个月前
  • 上一期大约在 1 个月前关闭,没有打开
  • 今天注意到,2018-03-14
于 2018-03-15T00:46:37.640 回答
1

您可以使用spyql。spyql 读取 json 文件(每行 1 个 json 对象)并生成可以通过管道传输到 sqlite 的 INSERT 语句:

$ spyql -Otable=my_table "SELECT json->uri, json->user_agent FROM json TO sql" < sample3.json | sqlite3 my.db

这假设您已经在 sqlite 数据库中创建了一个空表my.db

免责声明:我是 spyql 的作者。

于 2021-12-15T00:49:54.567 回答