当前位置: 首页 > 工具软件 > Tinydb > 使用案例 >

python使用轻量级数据库--tinydb

沈鸿光
2023-12-01

文档: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')

Document id的使用

在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来提高速度。它缓存所有读操作,并在配置的写操作次数后将数据写入磁盘。

为了确保关闭表时所有数据都被安全写入,请使用以下方法之一:

  1. with database as db:
  2. db.close()

插件使用

TinyDB带有类型注释,MyPy可以使用它来确保你正确地使用API。

不幸的是,MyPy并不理解TinyDB使用的所有代码模式。

出于这个原因,TinyDB发布了一个myypy插件,帮助正确地检查使用TinyDB的代码。

要使用它,将它添加到myypy配置文件中的插件列表(通常位于setup.cfg或MyPy .ini中):

[mypy]

plugins = tinydb.mypy_plugin

 类似资料: