这样就可以直接将JSON插入SQLite,然后将其提取数据并对其进行索引,即可以将SQLite视为文档数据库。这在PostgreSQL中是可行的,很明显是Elastic提供的,但是可以在嵌入式数据库中使用对于轻量级的东西来说非常好。
$ sqlite3SQLite版本3.31.1 2020-01-27 19:55:54已连接到瞬态内存数据库。sqlite> CREATE TABLE t(body TEXT,d INT GENERATED ALWAYS AS(json_extract(body,'$ .d')) VIRTUAL); sqlite>插入t值(json('{“ d”:“ 42”}')); sqlite> select * from t WHERE d = 42; {“ d”:“ 42”} | 42
(此外:在MacOS上编写Homebrew时,可能很难获得足够新的SQLite,否则您可能需要使用不稳定的源(如nixpkgs-unstable)。)
有一些不错的属性。通常,在插入时(通过json()函数)鼓励最小化和验证JSON,因为SQLite没有JSON类型,它将允许任何操作。但是,没有什么强制执行此操作,您可以添加一个约束,但是可能会忘记...生成始终使用json_extract意味着无效的JSON将得到错误:在插入时JSON格式错误。
sqlite> CREATE TABLE x(正文TEXT,ID TEXT GENERATED ALWAYS AS(json_extract(body,'$ .id'))VIRTUAL NOT NULL); sqlite> insert into x values('');错误:格式错误的JSONsqlite>插入x values('{}');错误:NOT NULL约束失败:x.id
我们可以通过添加NOTNULL来强制插入的JSON中存在项目,但是我们也可以使用约束和其他SQLite功能!
您会注意到我在这些示例中将VIRTUAL与生成的列一起使用。还有一个选择是使用STORED本质上缓存值,尽管缺点是您无法通过ALTER TABLE添加这些列。
但是,即使已将索引定义为虚拟索引,也始终可以在列上创建索引:
然后检查是否可以按预期工作:解释查询计划选择*从x WHERE id ='foo';查询计划-搜索表x使用INDEX xid(id =?)
ALTER TABLE x ADD COLUMN文本始终以(json_extract(body,'$ .text'))生成;直接插入x值(json('{“ id”:43,“ text”:“ test”}')) ;在x(text)上创建索引xtext;
这样做的好处是,您可以从一个表开始,该表可以像单个JSON列一样简单,并且可以在该JSON中找到有用的数据时添加列和索引。例如,这对于webhook非常有效,将您直接发送的所有数据插入表中,然后稍后取出有用的东西。