diff --git a/src/documents/search/_backend.py b/src/documents/search/_backend.py index 930a7f48c..aaa4ed395 100644 --- a/src/documents/search/_backend.py +++ b/src/documents/search/_backend.py @@ -1043,16 +1043,21 @@ class TantivyBackend: excluded from results. Args: - doc_id: Primary key of the reference document + doc_id: Primary key of the reference document, or of one of its + versions user: User for permission filtering (None for no filtering) limit: Maximum number of IDs to return (None = all matching docs) Returns: List of similar document IDs (excluding the original) """ + from documents.versioning import root_document_ids + self._ensure_open() searcher = self._index.searcher() + # Only root documents are indexed, so a version stands for its root + doc_id = next(iter(root_document_ids([doc_id])), doc_id) id_query = tantivy.Query.term_query(self._schema, "id", doc_id) results = searcher.search(id_query, limit=1) diff --git a/src/documents/search/_schema.py b/src/documents/search/_schema.py index 62130c246..cb686eabf 100644 --- a/src/documents/search/_schema.py +++ b/src/documents/search/_schema.py @@ -28,7 +28,9 @@ logger = logging.getLogger("paperless.search") # columns dropped. tantivy compares schemas by ordered field list, so an # index built by v1 rejects every write against the v2 schema. # v3 - barcodes JSON field for stored barcode contents -SCHEMA_VERSION: Final[int] = 3 +# v4 - root documents only. Earlier indexes may hold document versions under +# their own id and metadata, so they are rebuilt without them. +SCHEMA_VERSION: Final[int] = 4 # Present in the index directory from the moment a full rebuild starts until it # finishes. If a rebuild is interrupted it is left behind, so the half-built diff --git a/src/documents/tests/search/test_backend.py b/src/documents/tests/search/test_backend.py index 4350280f7..42c89c7fc 100644 --- a/src/documents/tests/search/test_backend.py +++ b/src/documents/tests/search/test_backend.py @@ -1136,6 +1136,34 @@ class TestMoreLikeThis: assert 150 not in ids assert 151 in ids + def test_more_like_this_ids_seeded_by_version_uses_root( + self, + backend: TantivyBackend, + ) -> None: + """A version is not indexed, so it must be looked up as its root.""" + root = DocumentFactory.create( + title="Important document", + content="financial information report", + ) + version = DocumentFactory.create( + title="Important document", + content="financial information report", + root_document=root, + version_index=1, + ) + other = DocumentFactory.create( + title="Another document", + content="financial information report", + ) + backend.add_or_update(root) + backend.add_or_update(other) + + ids = backend.more_like_this_ids(doc_id=version.pk, user=None) + + assert other.pk in ids + assert root.pk not in ids + assert version.pk not in ids + class TestSingleton: """Test get_backend() and reset_backend() singleton lifecycle."""