Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,32 @@ True
Using ``doc_id``/``doc_ids`` instead of ``Query()`` again is slightly faster
in operation.

Moving documents between databases
..................................

Documents returned by TinyDB are :class:`~tinydb.table.Document` instances.
They look like plain dicts, but they also carry the document ID assigned by
the table they came from. If you insert such a ``Document`` into another
table or database, TinyDB reuses that ID. When the target table already has
a document with the same ID, insertion fails with ``ValueError: Document
with ID ... already exists``.

This often shows up when moving documents from one database to another:

>>> db1 = TinyDB('db1.json')
>>> db2 = TinyDB('db2.json')
>>> document = db1.get(doc_id=1)
>>> db2.insert(document) # reuses doc_id=1 from db1
>>> db1.remove(doc_ids=[1])

To copy the document's data and let the target table assign a new ID, convert
the ``Document`` to a plain dict first:

>>> db2.insert(dict(document))

The same applies when moving documents between named tables in a single
database.

Recap
.....

Expand Down
19 changes: 19 additions & 0 deletions tests/test_tinydb.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,25 @@ def transform(el):
assert db.count(where('int') == 1) == 2


def test_move_document_between_tables(db: TinyDB):
source = db.table('source')
target = db.table('target')

doc_id = source.insert({'type': 'apple', 'count': 7})
target.insert({'placeholder': True})
document = source.get(doc_id=doc_id)

with pytest.raises(ValueError, match='already exists'):
target.insert(document)

new_id = target.insert(dict(document))
source.remove(doc_ids=[doc_id])

assert source.all() == []
assert target.get(doc_id=new_id) == {'type': 'apple', 'count': 7}
assert new_id == 2


def test_update_ids(db: TinyDB):
db.update({'int': 2}, doc_ids=[1, 2])

Expand Down