默认值 SqliteDatabase 已经包含许多特定于sqlite的功能:
- 有关使用SQLite的一般说明 .
- 使用PRAGMA语句配置SQLite.
- 用户定义的函数,聚合和排序规则 .
- 交易锁定模式 .
playhouse.sqlite_ext
包括更多的sqlite功能,包括:
- 全文搜索.
- JSON扩展集成.
- 闭包表扩展支持.
- LSM1扩展支持.
- 用户定义表功能.
- 使用备份API支持联机备份:
backup_to_file()
- BLOB API支持,用于高效的二进制数据存储. .
- 其他帮助, 包括布卢姆过滤器,更多。
class JSONField(json_dumps=None, json_loads=None, ...)
适用于存储JSON数据的字段类,具有设计用于 json1 extension 。
介绍
添加了sqlite 3.9.0扩展库形式的JSON支持。 SQLite json1扩展提供了许多用于处理JSON数据的辅助函数。 这些API作为特殊字段类型JSONField的方法公开。 要访问或修改JSON结构中的特定对象键或数组索引, 可以处理 JSONField 就像是一本字典、一张清单。
参数
json_dumps
:(可选)用于将数据序列化为JSON字符串的函数。 如果没有提供,将使用stdlib json.dumps
。json_loads
:(可选)用于将JSON反序列化为Python对象的函数。 如果没有提供,将使用stdlib json.loads
。
注解
要自定义JSON序列化或反序列化,可以指定自定义 json_dumps
和 json_loads
召唤物。
这些函数应该分别接受一个参数:要序列化的对象和JSON字符串。
要修改stdlib json
函数的参数,可以使用 functools.partial
:
# 不要转义unicode代码点。
my_json_dumps = functools.partial(json.dumps, ensure_ascii=False)
class SomeModel(Model):
# 指定我们的自定义序列化功能。
json_data = JSONField(json_dumps=my_json_dumps)
from playhouse.sqlite_ext import *
db = SqliteExtDatabase(':memory:')
class KV(Model):
key = TextField()
value = JSONField()
class Meta:
database = db
KV.create_table()
存储数据可以按预期工作。无需将字典或列表序列化为json,因为这是由peewee自动完成的:
KV.create(key='a', value={'k1': 'v1'})
<KV: 1>
KV.get(KV.key == 'a').value
{'k1': 'v1'}
可以使用字典查找访问JSON数据的特定部分:
KV.get(KV.value['k1'] == 'v1').key
'a'
可以使用 update()
方法。注意“k1=v1”保留:
KV.update(value=KV.value.update({'k2': 'v2', 'k3': 'v3'})).execute()
1
KV.get(KV.key == 'a').value
{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
可以自动更新现有数据,或者通过将键的值设置为来删除键。 在下面的示例中,将更新“k1”的值并删除“k3”(“k2”不会被修改):
KV.update(value=KV.value.update({'k1': 'v1-x', 'k3': None})).execute()
1
KV.get(KV.key == 'a').value
{'k1': 'v1-x', 'k2': 'v2'}
可以使用 set()
方法:
KV.update(value=KV.value['k1'].set('v1')).execute()
1
KV.get(KV.key == 'a').value
{'k1': 'v1', 'k2': 'v2'}
set()
除了标量值之外,方法还可以用于对象:
KV.update(value=KV.value['k2'].set({'x2': 'y2'})).execute()
1
KV.get(KV.key == 'a').value
{'k1': 'v1', 'k2': {'x2': 'y2'}}
可以使用原子方式删除JSON数据的各个部分。 remove()
:
KV.update(value=KV.value['k2'].remove()).execute()
1
KV.get(KV.key == 'a').value
{'k1': 'v1'}
可以使用 json_type()
方法:
KV.select(KV.value.json_type(), KV.value['k1'].json_type()).tuples()[:]
[('object', 'text')]
添加一个嵌套值,然后看看如何使用 tree()
方法:
KV.create(key='b', value={'x1': {'y1': 'z1', 'y2': 'z2'}, 'x2': [1, 2]})
<KV: 2>
tree = KV.value.tree().alias('tree')
query = KV.select(KV.key, tree.c.fullkey, tree.c.value).from_(KV, tree)
query.tuples()[:]
[('a', '$', {'k1': 'v1'}), ('a', '$.k1', 'v1'), ('b', '$', {'x1': {'y1': 'z1', 'y2': 'z2'}, 'x2': [1, 2]}), ('b', '$.x1', {'y1': 'z1', 'y2': 'z2'}), ('b', '$.x1.y1', 'z1'), ('b', '$.x1.y2', 'z2'), ('b', '$.x2', [1, 2]), ('b', '$.x2[0]', 1), ('b', '$.x2[1]', 2)]
tree()
和 children()
方法是强大的。
还要注意的是 JSONField 查找可以链接:
query = KV.select().where(KV.value['x1']['y1'] == 'z1')
for obj in query:
print(obj.key, obj.value)
b {'x1': {'y1': 'z1', 'y2': 'z2'}, 'x2': [1, 2]}
__getitem__(item)
:参数item
是访问JSON数据中的特定键或数组索引。
函数返回公开对JSON数据访问的特殊对象。返回类型JSONPath
.
访问JSON数据中的特定键或数组索引。返回A JSONPath 对象,
它公开了读取或修改JSON对象特定部分的方便方法。
示例:
# If metadata contains {"tags": ["list", "of", "tags"]}, we can
# extract the first tag in this way:
Post.select(Post, Post.metadata['tags'][0].alias('first_tag'))
set(value[, as_json=None])
: 参数value
, 标量值、列表或字典。as_json (bool)
,强制将该值视为JSON,在这种情况下, 它将在python中预先序列化为JSON。默认情况下, 列表和字典被视为要序列化的JSON,而字符串和整数则按原样传递。 设置存储在 JSONField .使用json_set()
来自JSON1扩展的函数。update(data)
:参数data
, 要与当前存储在 JSONField . 要删除特定的密钥,请将该密钥设置为 None 在更新的数据中。 使用RFC-7396 merge patch算法将新数据合并到json值中以应用补丁( data 参数)。 MergePatch可以添加、修改或删除JSON对象的元素, 这意味着update()
是两者的通用替换set()
和remove()
. MergePatch将JSON数组对象视为原子对象,因此update()
不能追加到数组, 也不能修改数组的单个元素。 RFC-7396:该规范定义了JSON合并补丁程序格式和处理规则。 合并修补程序格式主要用于HTTP PATCH方法, 作为描述对目标资源内容的一组修改的一种方式。remove()
:删除存储在 JSONField 。使用json_remove
来自JSON1扩展的函数。json_type()
: 返回一个标识列中存储的值类型的字符串。使用json_type
来自JSON1扩展的函数。length()
: 返回存储在列中的数组的长度。 使用json_array_length
来自JSON1扩展的函数。children()
: 这个 children 函数对应于json_each
, 一个表值函数,用于遍历所提供的JSON值并返回顶级数组或对象的直接子级。 如果指定了路径,则该路径将被视为最上面的元素。
调用返回的行 children()
具有以下属性:
- key :当前元素相对于其父元素的键。
- value :当前元素的值。
- type :数据类型之一(请参见
json_type()
) - atom :基元类型的标量值, NULL 用于数组和对象。
- id :引用树中当前节点的唯一ID。
- parent :包含节点的ID。
- fullkey :描述当前元素的完整路径。
- path :当前行的容器路径。
在内部,此方法使用 json_each
(文档链接)json1扩展中的函数。
示例用法与 tree()
方法如下:
from playhouse.sqlite_ext import *
db = SqliteExtDatabase('keyd')
class KeyData(Model):
key = TextField()
data = JSONField()
class Meta:
database = db
KeyData.create_table()
KeyData.create(key='a', data={'k1': 'v1', 'x1': {'y1': 'z1'}})
KeyData.create(key='b', data={'x1': {'y1': 'z1', 'y2': 'z2'}})
<KeyData: 12>
在KeyData模型中查询键以及其数据字段中的所有顶级键和值。
kd = KeyData.data.children().alias('children')
query = (KeyData
.select(kd.c.key, kd.c.value, kd.c.fullkey)
.from_(KeyData, kd)
.order_by(kd.c.key)
.tuples())
print(query[:])
[('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1')]
tree()
函数对应于 json_tree
,一个表值函数,
它递归地遍历所提供的JSON值,并返回有关每个级别的键的信息。
如果指定了路径,则该路径将被视为最上面的元素。
调用返回的行 tree()
具有与调用返回的行相同的属性 children()
:
- key :当前元素相对于其父元素的键。
- value :当前元素的值。
- type :数据类型之一(请参见
json_type()
) - atom :基元类型的标量值, NULL 用于数组和对象。
- id :引用树中当前节点的唯一ID。
- parent :包含节点的ID。
- fullkey :描述当前元素的完整路径。
- path :当前行的容器路径。
在内部,此方法使用 json_tree
(文档链接)json1扩展中的函数。
示例用法如下:
from playhouse.sqlite_ext import *
db = SqliteExtDatabase('keyd2')
class KeyData2(Model):
key = TextField()
data = JSONField()
class Meta:
database = db
KeyData2.create_table()
KeyData2.create(key='a', data={'k1': 'v1', 'x1': {'y1': 'z1'}})
KeyData2.create(key='b', data={'x1': {'y1': 'z1', 'y2': 'z2'}})
<KeyData2: 12>
递归地查询KeyData2模型中的键以及其数据字段中的所有键和值。
kd = KeyData2.data.tree().alias('tree')
query = (KeyData2.select(kd.c.key, kd.c.value, kd.c.fullkey)
.from_(KeyData2, kd)
.order_by(kd.c.key)
.tuples())
print(query[:])
[(None, '{"k1":"v1","x1":{"y1":"z1"}}', '$'), (None, '{"x1":{"y1":"z1","y2":"z2"}}', '$'), (None, '{"k1":"v1","x1":{"y1":"z1"}}', '$'), (None, '{"x1":{"y1":"z1","y2":"z2"}}', '$'), (None, '{"k1":"v1","x1":{"y1":"z1"}}', '$'), (None, '{"x1":{"y1":"z1","y2":"z2"}}', '$'), (None, '{"k1":"v1","x1":{"y1":"z1"}}', '$'), (None, '{"x1":{"y1":"z1","y2":"z2"}}', '$'), (None, '{"k1":"v1","x1":{"y1":"z1"}}', '$'), (None, '{"x1":{"y1":"z1","y2":"z2"}}', '$'), (None, '{"k1":"v1","x1":{"y1":"z1"}}', '$'), (None, '{"x1":{"y1":"z1","y2":"z2"}}', '$'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('k1', 'v1', '$.k1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('x1', '{"y1":"z1"}', '$.x1'), ('x1', '{"y1":"z1","y2":"z2"}', '$.x1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y1', 'z1', '$.x1.y1'), ('y2', 'z2', '$.x1.y2'), ('y2', 'z2', '$.x1.y2'), ('y2', 'z2', '$.x1.y2'), ('y2', 'z2', '$.x1.y2'), ('y2', 'z2', '$.x1.y2'), ('y2', 'z2', '$.x1.y2')]