文档:https://tinydb.readthedocs.io/en/latest/usage.html
Github:https://github.com/msiemens/tinydb
TinyDB 是一个纯 Python 编写的轻量级数据库,一共只有1800行代码,没有外部依赖项。
TinyDB的目标是降低小型 Python 应用程序使用数据库的难度,对于一些简单程序而言与其用 SQL 数据库,不如就用TinyDB, 因为它有如下特点:
轻便:当前源代码有 1800 行代码(大约 40% 的文档)和 1600 行测试代码。
可随意迁移:在当前文件夹下生成数据库文件,不需要任何服务,可以随意迁移。
简单:TinyDB 通过提供简单干净的 API 使得用户易于使用。
用纯 Python 编写:TinyDB 既不需要外部服务器,也不需要任何来自 PyPI 的依赖项。
适用于 Python 3.6+ 和 PyPy3:TinyDB 适用于所有现代版本的 Python 和 PyPy。
强大的可扩展性:您可以通过编写中间件修改存储的行为来轻松扩展 TinyDB。
100% 测试覆盖率:无需解释。
安装:pip install tinydb
导入使用:from tinydb import TinyDB, Query
初始化数据库:db=TinyDB('db.json')
初始化条件查询:Fruit = Query()
注:在初始化后,在指定目录生成文件,用于存储数据,query用于条件查询使用
常用格式如下:
插入 db.insert(...) Insert a document 在TinyDB内部,插入的每个文档都关联一个document ID。它在插入文档后返回。
获取数据 db.all() 获取文档所有内容 iter(db) Iter over all documents db.search(query) 获取与查询匹配的文档列表
更新数据 db.update(fields, query) 以字段更新与查询匹配的文档内容
删除 db.remove(query) 删除匹配的文档内容 db.truncate() 删除文档所有
条件使用
Query() 创建一个查询对象
Query().field == 2 匹配具有关键字段的任何文档 value == 2 (also possible: !=, >, >=, <, <=)
数据增删改查:
增:db.insert({'name':'L1','value':'18'})
删:db.remove(Fruit.name== ‘L1’)
改:db.update({'value':'24'},Fruit.name== 'Y1')
查:db.search(Fruit.name == 'L1')
展示文档中所有数据:db.all()
清空文档中所有数据:db.truncate()
Query().field.exists() 示例:db.search(User.name.exists())
判断是否存在名为field的字段
Query().field.matches(regex) 示例:db.search(User.name.matches('[aZ]*'))
用匹配正则表达式的整个字段匹配任何文档,是否存在regex相同的字段
Query().field.search(regex) 示例:db.search(User.name.search('b+'))
用匹配正则表达式的字段的子字符串匹配任何文档,字段中是否存在符合的regex字符串
Query().field.test(func, *args) 示例:db.search(User.age.test(test_func, 0, 21))
匹配函数返回True的任何文档,args为向fun中传递的参数值
Query().field.all(query | list) 示例:db.search(User.groups.all(['admin', 'user']))
如果给定一个查询,则匹配列表字段中的所有文档都与查询匹配的所有文档。
如果给定一个列表,则匹配列表字段中的所有文档都是给定列表的成员的所有文档
Query().field.any(query | list) 示例:db.search(User.groups.any(['admin', 'sudo']))
如果给定一个查询,则匹配列表字段中至少有一个文档与查询匹配的所有文档。
如果给定一个列表,则匹配列表字段中至少有一个文档是给定列表成员的所有文档
Query().field.one_of(list) 示例:db.search(User.name.one_of(['jane', 'john']))
如果字段包含在列表中,则进行匹配
查询的逻辑操作
~ (query) 与查询不匹配的文档
(query1) & (query2) 匹配两个查询的文档
(query1) | (query2) 至少匹配其中一个查询的文档
db.insert_multiple(...) 插入多个文档
示例:
插入多条:db.insert_multiple([{'name':'L1','value':'21'},{'name':'S1','value':'21'}])
循环插入数组中多条:db.insert_multiple({'name': 'L1', 'value': i} for i in range(2))
根据ID插入:db.insert(Document({'name': 'L1', 'value': '21'},doc_id=12))
db.update(operation, ...) 用特殊操作更新所有匹配的文档
当将字典传递给db时。更新(字段,查询),它只允许通过添加或覆盖其值来更新文档。
但有时可能需要删除一个字段或增加它的值。在这种情况下,你可以传递一个函数而不是字段,TinyDB自带这些操作:
导入方法:from tinydb.operations import *
delete (key):删除文档中的一个密钥
increment (key):增加键的值
decrement (key):减少键值
add (key, value):将值添加到键的值(也适用于字符串)
subtract (key, value):从键的值中减去值
set (key, value):将key设置为value
示例:db.update_multiple([(delete('value'), where('name') == 'S1'),({'value':'11'}, where('name') == 'L1')])
db.upsert()
在某些情况下,需要同时使用update和insert: upsert。该操作提供了一个文档和一个查询。
如果它发现任何与查询匹配的文档,则将使用所提供文档中的数据更新这些文档。
另一方面,如果没有找到匹配的文档,它会将提供的文档插入到表中:
示例:db.upsert({'name': 'L2', 'value': '21'},where('name') == 'L2')
有几种方法可以从数据库中检索数据。例如:
获取存储文档的数量: len(db)
获取指定文档: db.get(where('name') == 'L2')
注:如果多个文档与查询匹配,可能会返回其中一个随机的文档!
判断文档是否存在: db.contains(where('name') == 'L2')
统计文档的数量: db.count(where('name') == 'L2')
在TinyDB内部,插入的每个文档都关联一个ID。它在插入文档后返回:
print_value(db.insert({'name':'S2','value':'16'}))
此外,可以使用document.doc_id获取已插入文档的ID。这对get和all都有效:
db.get(where('name') == 'L2').doc_id
db.all()[-1].doc_id
db.all()[0].doc_id
不同的TinyDB方法也适用于id,即:更新,删除,包含和获取。前两个还返回受影响id的列表。
db.update({'value': 2}, doc_ids=[1, 2])
db.contains(doc_id=1)
db.remove(doc_ids=[1, 2])
db.get(doc_id=3)
TinyDB支持使用多个表。它们的行为与TinyDB类相同。
要创建和使用表,请使用db.table(name)。
创建:table = db.table('table_name')
插入数据:table.insert({'value': True})
输出表数据:[print (tb) for tb in table]
获取表数据:table.all()
删除:db.drop_table('table_name')
删除所有:db.drop_tables()
获取所有的表:db.tables()
TinyDB使用一个名为_default的表作为默认表。
所有对数据库对象的操作(如db.insert(…))都在这个表上操作。
这个表的名字可以通过设置default_table_name类变量来修改所有实例的默认表名:
db = TinyDB(storage=SomeStorage)
db.default_table_name = 'my-default'
或者 TinyDB.default_table_name = 'my-default'
TinyDB缓存性能查询结果。这样,只要数据库没有被修改,重新运行查询就不必从存储中读取数据。
你可以通过将cache_size传递给table(…)函数来优化查询缓存大小:
table = db.table('table_name', cache_size=30)
注:可以将cache_size设置为None,使缓存大小无限制。此外,可以将cache_size设置为0来禁用它。
注:不可能使用不同的设置多次打开同一个表。在第一次调用之后,所有后续调用都将返回与第一次调用具有相同设置的同一个表。
注:TinyDB查询缓存不会检查数据库使用的底层存储是否已被外部进程修改。
在这种情况下,查询缓存可能返回过时的结果。要清除缓存并再次从存储中读取数据,可以使用db.clear_cache()。
注:当使用无限缓存大小和test()查询时,TinyDB将存储对test函数的引用。
由于这种行为,使用lambda函数作为测试函数的长时间运行的应用程序可能会出现内存泄漏。
TinyDB有两种存储类型:JSON和内存中。
默认情况下,TinyDB将其数据存储在JSON文件中,所以你必须指定存储它的路径:
db = TinyDB('path/to/db.json')
要使用内存存储,使用:
db = TinyDB(storage=MemoryStorage)
注:除storage参数外的所有参数都被转发到底层存储。
对于JSON存储,可以使用它将其他关键字参数传递给Python的JSON .dump(…)方法。
例如,可以设置它来创建美化的JSON文件,如:
db = TinyDB('db.json', sort_keys=True, indent=4, separators=(',', ': '))
要修改所有TinyDB实例的默认存储,设置default_storage_class类变量:
TinyDB.default_storage_class = MemoryStorage
如果需要直接访问存储实例,可以使用TinyDB实例的存储属性。这对于直接在存储或中间件上调用方法可能很有用:
db = TinyDB(storage=CachingMiddleware(MemoryStorage))
db.storage.flush()
中间件围绕现有的存储,允许自定义它们的行为。
from tinydb.storages import JSONStorage
from tinydb.middlewares import CachingMiddleware
db = TinyDB('/path/to/db.json', storage=CachingMiddleware(JSONStorage))
可以嵌套中间件:
db = TinyDB('/path/to/db.json',storage=FirstMiddleware(SecondMiddleware(JSONStorage)))
CachingMiddleware通过减少磁盘I/O来提高速度。它缓存所有读操作,并在配置的写操作次数后将数据写入磁盘。
为了确保关闭表时所有数据都被安全写入,请使用以下方法之一:
TinyDB带有类型注释,MyPy可以使用它来确保你正确地使用API。
不幸的是,MyPy并不理解TinyDB使用的所有代码模式。
出于这个原因,TinyDB发布了一个myypy插件,帮助正确地检查使用TinyDB的代码。
要使用它,将它添加到myypy配置文件中的插件列表(通常位于setup.cfg或MyPy .ini中):
[mypy]
plugins = tinydb.mypy_plugin