diff --git a/docs/usage.rst b/docs/usage.rst index 7b59566a..781f029a 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -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 ..... diff --git a/tests/test_tinydb.py b/tests/test_tinydb.py index 762a460b..d8c29f0d 100644 --- a/tests/test_tinydb.py +++ b/tests/test_tinydb.py @@ -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])