尧图精选

TinyDB 完整 API 架构解析:核心类、查询缓存与存储层设计指南

🕒 发布时间:2026/9/28 9:15:45 📁 来源:尧图网络
数据库嵌入式数据库【免费下载链接】tinydbTinyDB is a lightweight document oriented database optimized for your happiness :)项目地址https://gitcode.com/gh_mirrors/ti/tinydb点击查看免费下载TinyDB 是一个轻量级文档型数据库其 API 采用核心 API 持久化层 支撑组件三层架构应用代码通过TinyDB与Table操作文档Storage负责序列化与落盘Middleware、LRUCache等组件在读写链路中提供缓存与扩展能力。本篇以 docs/api.rst 为骨架结合仓库源码深入剖析每个模块的类、方法与数据流读完你可以完整掌握 TinyDB 的 API 全貌、查询缓存机制、存储与中间件扩展点并知道如何基于这些接口自定义存储和中间件。架构总览三层分离的设计TinyDB 的整体 API 划分为三个层次核心 API 层应用代码直接交互的TinyDB、Table、Document与查询对象持久化层负责序列化数据库状态并存储到内存或磁盘的Storage及其子类支撑组件层内部使用的查询缓存LRUCache、查询哈希freeze/FrozenDict以及读写拦截器Middleware。三层之间的协作关系如下中心是 tinydb/database.py 中的TinyDB它持有一个Storage实例并管理一个或多个 tinydb/table.py 中的Table对象每个表把文档存储为Document实例——一种同时暴露doc_id的 dict-like 对象查询由 tinydb/queries.py 中的Query与QueryInstance构建并执行持久化由Storage的子类如JSONStorage、MemoryStorage完成你可以用Middleware如CachingMiddleware包裹存储来改变读写处理方式。下面的架构图来自仓库 docs/_static/architecture.svg直观展示了这些类之间的关联典型数据流原文档给出了四条典型数据流这里结合源码逐步展开调用入口转发你在TinyDB实例上调用insert、search等方法时除非显式打开了命名表否则调用会被转发到默认表。这一机制由TinyDB.__getattr__实现tinydb/database.py它把所有未知属性访问转发给self.table(self.default_table_name)其中默认表名为_default类变量default_table_name见 tinydb/database.py。魔法方法如__len__、__iter__不会被__getattr__捕获因此代码中手动转发给了默认表tinydb/database.py。查询求值与缓存Table将QueryInstance作用于其文档集合。若查询可缓存结果会优先从表级LRUCache查询缓存返回。实现见 tinydb/table.pysearch()先检查self._query_cache.get(cond)命中则返回cached_results[:]一份新列表未命中则遍历self._read_table().items()逐条执行cond(doc)并把结果按query_cache_class缓存。整库读写表发生变化时通过其Storage实例读写完整的数据库状态。这是因为存储接口只支持整体读写见Table._update_table的说明tinydb/table.py先storage.read()拿到全部数据在内存中执行更新回调再把结果storage.write()写回最后清空查询缓存。局部字段更新对于部分文档更新tinydb/operations.py 提供delete、add、subtract、set、increment、decrement等辅助可调用对象可作为Table.update的第一个参数传入。如果你计划扩展 TinyDB建议先阅读 docs/extend.rst 了解自定义存储与中间件的写法再使用下文各模块的类参考获取方法级细节。tinydb.database数据库主类 TinyDBTinyDB是整个库的门面tinydb/database.py职责包括创建存储类实例、管理数据库表用一个以表名为键的普通dict存放表实例、以及提供对默认表的访问。数据存储模型TinyDB 把全部数据建模为一个嵌套dict存储类负责对其持久化{ table1: { 0: {document...}, 1: {document...}, }, table2: { ... } }外层键是表名内层键是文档 ID值即文档本身。TinyDB.tables()通过set(self.storage.read() or {})直接由该 dict 的键构造表名集合若存储为空文件返回None则返回空集合tinydb/database.py。构造参数与可定制类变量db TinyDB(db.json) # 默认 JSONStorage db TinyDB(storageMemoryStorage) # 纯内存存储 db TinyDB(db.json, ensure_asciiFalse) # 传给存储构造器的额外参数storage使用的存储类默认default_storage_class JSONStorage在__init__中通过kwargs.pop(storage, self.default_storage_class)取出其余args/kwargs全部透传给存储类的构造器tinydb/database.py可定制类变量版本 4.0 起table_class Table建表使用的类、default_table_name _default默认表名、default_storage_class JSONStorage默认存储类。核心方法方法说明实现要点table(name, **kwargs)获取指定表未访问过则用table_class新建并缓存已有实例直接返回否则self.table_class(self.storage, name, **kwargs)tinydb/database.pytables()返回全部表名集合set(self.storage.read() or {})drop_tables()删除所有表不可恢复向存储写入空 dict 并清空_tablesdrop_table(name)删除指定表不可恢复从内存实例与存储数据中一并移除storage属性返回底层存储实例直接返回self._storageclose()关闭数据库触发存储清理置_opened False并调用storage.close()__enter__/__exit__上下文管理器支持退出时若仍打开则自动close()close()的官方用法是配合上下文管理器确保文件句柄被正确释放with TinyDB(data.json) as db: db.insert({foo: bar}) # 离开 with 块时自动调用 close()测试 tests/test_tinydb.py 验证了close()只会被调用一次test_storage_closed_once防止析构阶段重复关闭。tinydb.table表与文档Document带 ID 的文档对象Document是dict的子类tinydb/table.py构造时接收Mapping内容与doc_id从而同时提供内容访问与 ID 访问doc Document({name: Alice}, doc_id3) doc[name] # Alice doc.doc_id # 3测试 tests/test_tinydb.py 展示了利用Document指定doc_id执行upsert的行为。插入时若传入Document实例其doc_id会被保留Table.inserttinydb/table.py重复 ID 会抛出ValueError。Table 的可定制类变量与TinyDB类似Table也暴露四个可覆盖的类变量版本 4.0 起tinydb/table.pydocument_class Document文档表示类document_id_class int文档 ID 类型query_cache_class LRUCache查询缓存类default_query_cache_capacity 10查询缓存默认容量。构造参数为Table(storage, name, cache_size10, persist_emptyFalse)。persist_emptyTrue时即使表还没有任何操作也会先落盘一个空表tinydb/table.py。读写方法全览Table是数据访问与操纵的核心提供以下方法方法功能返回值insert(document)插入单个文档新文档 IDintinsert_multiple(documents)批量插入支持列表与生成器插入 ID 列表all()获取全部文档list[Document]search(cond)按条件搜索可命中查询缓存list[Document]get(condNone, doc_idNone, doc_idsNone)取单个/多个文档不存在返回NoneDocument、list[Document]或Nonecontains(condNone, doc_idNone)判断是否存在匹配文档boolupdate(fields, condNone, doc_idsNone)更新匹配文档字段 dict 或变换函数被更新文档 ID 列表update_multiple(updates)一次执行多组字段/条件更新被更新文档 ID 列表upsert(document, condNone)存在则更新否则插入受影响文档 ID 列表remove(condNone, doc_idsNone)删除匹配文档无条件删除会抛RuntimeError提示用truncate()被删除文档 ID 列表truncate()清空表内全部文档无count(cond)统计匹配文档数len(self.search(cond))intclear_cache()清空查询缓存无update 的两种形态fields可以是一个Mapping对匹配文档执行table[doc_id].update(fields)也可以是一个可调用对象对匹配文档原地执行fields(table[doc_id])这正是 tinydb/operations.py 中辅助函数被使用的入口tinydb/table.py。按 ID 操作的原子性与静默跳过update/remove使用doc_ids时不存在的 ID 会被静默跳过返回列表只包含实际被操作更新/删除的 ID且操作是原子的——要么所有存在的目标都被处理要么一个都不处理。实现先过滤出存在的 ID 再统一执行tinydb/table.py 与 tinydb/table.py测试见 tests/test_tinydb.py。查询缓存LRU 与失效策略Table使用LRUCache实现查询缓存tinydb/table.py每次search都会更新缓存只缓存is_cacheable()为真的查询写入数据insert/update/remove 等时整个缓存被丢弃因为查询结果可能已变化——_update_table末尾调用self.clear_cache()tinydb/table.pysearch返回的是缓存列表的浅拷贝cached_results[:]但其中的文档对象与缓存共享可以随意修改返回的列表本身却不应修改列表内的文档改字段或嵌套值会污染后续相同查询的结果。测试 tests/test_tinydb.py 专门验证了这一语义。tinydb.queries查询构建与执行Query 与 QueryInstance 的分工Query是查询构建器QueryInstance是实际执行查询的对象tinydb/queries.py。查询对象同时是条件本身调用q(doc)返回bool。由于查询必须可作为缓存键QueryInstance保存一个稳定哈希值_hash并以(and, frozenset([...]))等元组结构组合AND/OR 使用frozenset保证交换律见 tinydb/queries.py。两种构建语法from tinydb import TinyDB, Query, where db TinyDB(db.json) # 1) ORM 风格 User Query() db.search(User.name John Doe) db.search(User[logged-in] True) # 2) 经典风格where 是 Query()[key] 的简写 db.search(where(value) True)其中where(key)等价于Query()[key]tinydb/queries.py。字段路径支持嵌套访问Query().network.id 114测试 tests/test_tinydb.py 验证了嵌套查询与删除。支持的比较与条件方法方法语义备注、!、、、、与常量比较哈希值中对右值做freeze处理exists()字段存在即匹配matches(regex, flags0)正则整串匹配内部用re.match非字符串值返回Falsesearch(regex, flags0)正则子串匹配内部用re.searchtest(func, *args)用户自定义测试函数函数必须确定性否则会破坏查询缓存any(cond)列表中任一元素满足条件条件可为查询或值列表all(cond)列表中全部元素满足条件one_of(items)值包含在给定列表中fragment(document)文档包含给定子集字段且值相等允许空路径noop()恒为True用于动态组合查询的基准值map(fn)向查询路径追加任意函数会使查询不可缓存_hash None查询还可以用二元AND、|OR与一元~NOT组合db.search((where(field1).exists()) (where(field2) 5)) db.search((where(field1).exists()) | (where(field2) 5))可缓存性is_cacheable为了让查询能作为 dict 键TinyDB 要求查询具有稳定哈希。QueryInstance.is_cacheable()返回self._hash is not Nonetinydb/queries.py。若查询哈希值中含有无法freeze的对象如 numpy 数组构造时会捕获TypeError并把哈希置为None从而自动降级为不可缓存tinydb/queries.py。自定义查询对象若涉及远程查找等非确定性逻辑应实现is_cacheable返回False。测试 tests/test_tinydb.py 演示了带is_cacheable lambda: False的 lambda 查询不会被缓存。tinydb.operations局部字段更新辅助函数operations模块为Table.update提供一组现成的变换函数tinydb/operations.py用法from tinydb.operations import delete, add, subtract, set, increment, decrement db.update(delete(foo), where(foo) 2) # 删除 foo 字段 db.update(increment(counter), where(name) Alice) db.update(set(status, active), where(id) 1)函数签名行为deletedelete(field)删除文档中的指定字段addadd(field, n)给指定字段加nint/floatsubtractsubtract(field, n)给指定字段减nsetset(field, val)把字段设置为valincrementincrement(field)字段自增 1decrementdecrement(field)字段自减 1每个函数返回一个接收MutableMapping的变换 callable与update(fields, cond)中 callable 分支完全兼容tinydb/table.py。测试 tests/test_tinydb.py 同时演示了手写变换函数与operations.delete两种方式。tinydb.storages存储层Storage 抽象基类Storage是全部存储的抽象基类tinydb/storages.py用ABC保证子类必须实现read与writeread()读取最后存储的状态反序列化应在此处完成返回None表示存储为空TinyDB 据此做内部初始化write(data)把数据库当前状态写入存储序列化应在此处完成close()可选用于关闭文件句柄等清理工作。JSONStorage基于 JSON 文件的存储默认存储tinydb/storages.py构造参数JSONStorage(path, create_dirsFalse, encodingNone, access_moder, **kwargs)pathJSON 文件路径create_dirs是否自动创建缺失的父目录默认Falseencoding文件编码access_mode文件打开模式默认r。使用r/rb/r/rb之外的模式会发出警告因为可能导致数据丢失或损坏tinydb/storages.py**kwargs透传给json.dumps的参数例如ensure_asciiFalse测试 tests/test_tinydb.py 即使用了该参数。注意切勿把不受信任或用户可控的代码传入kwargs如cls、default它们会在每次写操作时被调用存在安全风险。写入时先seek(0)定位到文件头json.dumps序列化后写入flush()与os.fsync()确保落盘最后truncate()清除文件变短后的残留数据tinydb/storages.py。读取时若文件为空返回None否则json.load载入tinydb/storages.py。MemoryStorage内存存储MemoryStoragetinydb/storages.py把状态保存在实例属性self.memory中read()直接返回write(data)直接赋值。适合测试与临时数据场景例如测试夹具 tests/conftest.py 中的大量用例。tinydb.middlewares读写拦截中间件Middleware 基类Middleware是中间件的基类tinydb/middlewares.py作用是挂钩 TinyDB 的读写流程从而添加缓存、日志等扩展行为构造时传入真实的存储类__init__必须调用父类构造器super().__init__(storage_cls)通过__call__完成存储实例的惰性创建self.storage self._storage_cls(*args, **kwargs)并返回self这样TinyDB(storageMiddleware(StorageClass))中storage(*args, **kwargs)的调用会被转发到__call__tinydb/middlewares.py多层中间件嵌套时__call__会逐层初始化__getattr__把未覆盖的属性访问透明转发给底层存储tinydb/middlewares.pystorage属性提供对底层存储实例的访问。基类约定若read()/write()未被覆盖则直接转发给存储实例。CachingMiddleware写缓存中间件内置实现tinydb/middlewares.py旨在提升性能读总是从内存缓存读取self.cache缓存为空时才真正访问底层存储写数据先写入缓存每WRITE_CACHE_SIZE类变量默认 1000次写操作才真正刷盘一次flush()把未写入数据强制写入底层存储close()先flush()再关闭底层存储避免丢失缓存中尚未落盘的数据已关闭的中间件上执行读写会抛出ValueError(I/O operation on closed storage)。from tinydb import TinyDB from tinydb.middlewares import CachingMiddleware from tinydb.storages import JSONStorage db TinyDB(storageCachingMiddleware(JSONStorage))测试 tests/test_tinydb.py 验证了TinyDB(storageCachingMiddleware(MemoryStorage)).storage的类型是CachingMiddleware本身。tinydb.utils内部支撑工具utils模块提供三个内部支撑组件tinydb/utils.pyLRUCache查询缓存的底层实现LRUCache是一个固定容量的最近最少使用缓存tinydb/utils.py行为类似dict但容量超限时丢弃最久未使用的条目内部用OrderedDict实现每次访问把条目move_to_end移到末尾__getitem__/gettinydb/utils.pyset时若超出capacity则popitem(lastFalse)移除最旧条目tinydb/utils.py容量为None时缓存不限大小暴露lru属性按最近使用排序的键列表与length属性。Table的查询缓存即默认使用此类默认容量 10default_query_cache_capacity。如需调整可通过TinyDB.table_class.default_query_cache_capacity 100全局修改见 docs/extend.rst。freeze / FrozenDict查询稳定哈希的关键查询哈希要求右值可哈希。freeze(obj)tinydb/utils.py递归地把对象变为不可变、可哈希形式dict→FrozenDictlist→tupleset→frozenset。FrozenDicttinydb/utils.py禁用了所有写操作并以hash(tuple(sorted(self.items())))实现哈希。这样Query().f1 {a: 1}这类含 dict 的查询也能获得稳定哈希并被缓存。with_typehint类型提示转发with_typehint(baseclass)tinydb/utils.py在类型检查环境下让目标类假装继承指定基类从而把Table的方法签名透传给TinyDBPyCharm、Pyright/VS Code 支持该模式MyPy 则需要仓库中的 tinydb/mypy_plugin.py 插件支持配置见 mypy.ini。扩展入口从 API 走向自定义docs/api.rst明确指出扩展 TinyDB 应首先阅读 docs/extend.rst其中有四种途径自定义 Storage继承Storage实现read/write/close。TinyDB(db.yml, storageYAMLStorage)中除storage外的所有参数都会传给存储构造器未初始化时read()应返回None需要清理时实现close()并配合with TinyDB(...) as db:使用。自定义 Middleware继承Middleware构造器必须super().__init__(storage_cls)通过self.storage访问底层存储数据形态是表名 → {doc_id: doc}的嵌套 dict。使用时TinyDB(storageRemoveEmptyItemsMiddleware(SomeStorageClass))。hooks 与覆盖点修改TinyDB.default_table_name、TinyDB.table_class.default_query_cache_capacity等类变量。子类化TinyDB与Table例如class MyTable(Table): ...后TinyDB.table_class MyTable深度改变库的行为。所有扩展点的类与方法细节均可回到本文所述各模块的源码tinydb/database.py、tinydb/table.py、tinydb/storages.py、tinydb/middlewares.py中继续查阅。赞分享数据库嵌入式数据库【免费下载链接】tinydbTinyDB is a lightweight document oriented database optimized for your happiness :)项目地址https://gitcode.com/gh_mirrors/ti/tinydb点击查看免费下载相关推荐如何3分钟掌握AI视频插帧神器Flowframes让普通视频秒变流畅大片如何3分钟掌握AI视频插帧神器Flowframes让普通视频秒变流畅大片 想要将30帧视频瞬间升级到120帧的丝滑体验吗 Flowframes AI视频插帧视频处理桌面应用AI 应用人工智能普通鼠标在macOS上如何脱胎换骨开源工具Mac Mouse Fix完整上手指南普通鼠标在macOS上如何脱胎换骨开源工具Mac Mouse Fix完整上手指南 如果你刚换到Mac多半经历过这样的一幕旁边同事用触控板三指一划就切换桌面应用系统编程MessageDisplayKit核心架构解析网络层、缓存层与数据层MessageDisplayKit核心架构解析网络层、缓存层与数据层 MessageDisplayKit作为一款仿微信的即时通讯框架其核心架构设计体现了现代上一篇Album AI商业化探索企业如何利用智能相册技术提升效率下一篇Promptise Foundry测试策略单元测试、集成测试与端到端测试最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →