TinyDB is a lightweight document oriented database optimized for your happiness :) It's written in pure Python and has no external dependencies. The target are small apps that would be blown away by a SQL-DB or an external database server.
TinyDB is:
- tiny: The current source code has 1200 lines of code (with about 40% documentation) and 1000 lines tests. For comparison: Buzhug has about 2500 lines of code (w/o tests), CodernityDB has about 7000 lines of code (w/o tests).
- document oriented: Like MongoDB, you can store any document
(represented as
dict
) in TinyDB. - optimized for your happiness: TinyDB is designed to be simple and fun to use by providing a simple and clean API.
- written in pure Python: TinyDB neither needs an external server (as e.g. PyMongo) nor any dependencies from PyPI.
- works on Python 2.6 + 2.7 and 3.3 – 3.6 and PyPy: TinyDB works on all modern versions of Python and PyPy.
- powerfully extensible: You can easily extend TinyDB by writing new storages or modify the behaviour of storages with Middlewares.
- 100% test coverage: No explanation needed.
To dive straight into all the details, head over to the TinyDB docs. You can also discuss everything related to TinyDB like general development, extensions or showcase your TinyDB-based projects on the discussion forum.
>>> from tinydb import TinyDB, Query
>>> db = TinyDB('/path/to/db.json')
>>> db.insert({'int': 1, 'char': 'a'})
>>> db.insert({'int': 1, 'char': 'b'})
>>> User = Query()
>>> # Search for a field value
>>> db.search(User.name == 'John')
[{'name': 'John', 'age': 22}, {'name': 'John', 'age': 37}]
>>> # Combine two queries with logical and
>>> db.search((User.name == 'John') & (User.age <= 30))
[{'name': 'John', 'age': 22}]
>>> # Combine two queries with logical or
>>> db.search((User.name == 'John') | (User.name == 'Bob'))
[{'name': 'John', 'age': 22}, {'name': 'John', 'age': 37}, {'name': 'Bob', 'age': 42}]
>>> # More possible comparisons: != < > <= >=
>>> # More possible checks: where(...).matches(regex), where(...).test(your_test_func)
>>> table = db.table('name')
>>> table.insert({'value': True})
>>> table.all()
[{'value': True}]
>>> from tinydb.storages import JSONStorage
>>> from tinydb.middlewares import CachingMiddleware
>>> db = TinyDB('/path/to/db.json', storage=CachingMiddleware(JSONStorage))
TinyDB has been tested with Python 2.6, 2.7, 3.3 - 3.5 and PyPy.
tinyindex
tinymongo
TinyMP
tinyrecord
tinydb-serialization
tinydb-serialization
provides serialization for objects
that TinyDB otherwise couldn't handle.tinydb-smartcache
tinydb-smartcache
provides a smart query cache for
TinyDB. It updates the query cache when
inserting/removing/updating documents so the cache doesn't
get invalidated. It's useful if you perform lots of queries
while the data changes only little.Whether reporting bugs, discussing improvements and new ideas or writing extensions: Contributions to TinyDB are welcome! Here's how to get started:
- Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug
- Fork the repository on Github, create a new branch off the master branch and start making your changes (known as GitHub Flow)
- Write a test which shows that the bug was fixed or that the feature works as expected
- Send a pull request and bug the maintainer until it gets merged and published ☺
- nothing yet
- Feature:
one_of
for checking if a value is contained in a list (see issue 164) - Feature: Upsert (insert if document doesn't exist, otherwise update; see https://forum.m-siemens.de/d/30-primary-key-well-sort-of)
- Internal change: don't read from storage twice during initialization (see https://forum.m-siemens.de/d/28-reads-the-whole-data-file-twice)
- Allow updating all documents using
db.update(fields)
(see issue #157). - Rename elements to documents. Document IDs now available with
doc.doc_id
, usingdoc.eid
is now deprecated (see pull request #158)
- Expose the table name via
table.name
(see issue #147). - Allow better subclassing of the
TinyDB
class (see pull request #150).
- Expose TinyDB version via
import tinyb; tinydb.__version__
(see issue #148).
- Add new update operations:
add(key, value)
,substract(key, value)
, andset(key, value)
(see pull request #145).
- Use relative imports to allow vendoring TinyDB in other packages (see pull request #142).
- Allow iterating over a database or table yielding all documents (see pull request #139).
- Fix bug with accidental modifications to the query cache when modifying the list of search results (see issue #132).
- Fix the
Query
constructor to prevent wrong usage (see issue #117).
- Fix a bug with queries on documents that have a
path
key (see pull request #107). - Don't write to the database file needlessly when opening the database (see pull request #104).
- Add a way to specify the default table name via default_table (see pull request #98).
- Add
db.purge_table(name)
to remove a single table (see pull request #100).- Along the way: celebrating 100 issues and pull requests! Thanks everyone for every single contribution!
- Extend API documentation (see issue #96).
- Fix a bug when that breaks the JSONStorage when the
TinyDB
instance gets garbagge collected (see issue #92).
- Fix a bug when using unhashable documents (lists, dicts) with
Query.any
orQuery.all
queries (see a forum post by karibul).
- Inserting a dictionary with data that is not JSON serializable doesn't lead to corrupt files anymore (see issue #89).
- Fix a bug in the LRU cache that may lead to an invalid query cache (see issue #87).
db.update(...)
anddb.remove(...)
now return affected document IDs (see issue #83).- Inserting an invalid document (i.e. not a
dict
) now raises an error instead of corrupting the database (see issue #74).
- Overhauled Query model:
where('...').contains('...')
has been renamed towhere('...').search('...')
.- Support for ORM-like usage:
User = Query(); db.search(User.name == 'John')
. where('foo')
is an alias forQuery().foo
.where('foo').has('bar')
is replaced by eitherwhere('foo').bar
orQuery().foo.bar
.- In case the key is not a valid Python identifier, array
notation can be used:
where('a.b.c')
is nowQuery()['a.b.c']
.
- In case the key is not a valid Python identifier, array
notation can be used:
- Checking for the existence of a key has to be done explicitely:
where('foo').exists()
.
- Migrations from v1 to v2 have been removed.
SmartCacheTable
has been moved to msiemens/tinydb-smartcache.- Serialization has been moved to msiemens/tinydb-serialization.
- Empty storages are now expected to return
None
instead of raisingValueError
. (see issue #67.
- Allow custom parameters for custom test functions (see issue #63 and pull request #64).
- Fix a forgotten debug output in the
SerializationMiddleware
(see issue #55). - Fix an "ignored exception" warning when using the
CachingMiddleware
(see pull request #54) - Fix a problem with symlinks when checking out TinyDB on OSX Yosemite (see issue #52).
- Hopefully fix a problem with using TinyDB as a dependency in a
setup.py
script (see issue #51).
- Added support for custom serialization. That way, you can teach TinyDB
to store
datetime
objects in a JSON file :) (see issue #48 and pull request #50) - Fixed a performance regression when searching became slower with every search (see issue #49)
- Internal code has been cleaned up
- Fixed a data loss when using
CachingMiddleware
together withJSONStorage
(see issue #47)
- Fixed handling of IDs with the JSON backend that converted integers to strings (see issue #45)
- Extended
any
andall
queries to take lists as conditions (see pull request #38) - Fixed an
decode error
when installing TinyDB in a non-UTF-8 environment (see pull request #37) - Fixed some issues with
CachingMiddleware
in combination withJSONStorage
(see pull request #39)
- Added
where(...).contains(regex)
(see issue #32) - Fixed a bug that corrupted data after reopening a database (see issue #34)
- Fixed handling of Unicode data in Python 2 (see issue #28).
Warning: TinyDB changed the way data is stored. You may need to migrate your databases to the new scheme. Check out the Upgrade Notes for details.
- The syntax
query in db
has been removed, usedb.contains
instead. - The
ConcurrencyMiddleware
has been removed due to a insecure implementation (see Issue #18). Consider tinyrecord instead. - Better support for working with Element IDs.
- Added support for nested comparisons.
- Added
all
andany
comparisons on lists. - Added optional smart query caching.
- The query cache is now a fixed size LRU cache.
- Added
insert_multiple
function (see issue #8).
- Fixed bug #7: IDs not unique.
- Extended the API:
db.count(where(...))
anddb.contains(where(...))
. - The syntax
query in db
is now deprecated and replaced bydb.contains
.
- Added
update
method (see issue #6).
- Merged PR #5: Fix minor documentation typos and style issues.
- Improved the docs and fixed some typos.
- Refactored some internal code.
- Fixed a bug with multiple
TinyDB?
instances.
- Fixed a bug in
JSONStorage
that broke the database when removing entries.
- First official release – consider TinyDB stable now.