diff --git a/README.rst b/README.rst index f547d6e559..7e7f490264 100644 --- a/README.rst +++ b/README.rst @@ -87,7 +87,7 @@ Install and run locally from a virtual environment #. For docs (next step requires ``gettext``):: python -m manage loaddata doc_releases - python -m manage update_docs --update-index + python -m manage update_docs #. For dashboard: @@ -236,16 +236,8 @@ minified version of it to this directory. Documentation search -------------------- -When running ``python -m manage update_docs --update-index`` to build all -documents it will also automatically index every document it builds in the -search engine as well. In case you've already built the documents and would like -to reindex the search index, run the command:: - - python -m manage update_index - -This is also the right command to run when you work on the search feature -itself. You can pass the ``-d`` option to try to drop the search index -first before indexing all the documents. +When running ``python -m manage update_docs`` to build all documents it will +also automatically index every document it builds in the search engine as well. Updating metrics from production -------------------------------- diff --git a/docker-entrypoint.dev.sh b/docker-entrypoint.dev.sh index 11a38190b0..3a42356298 100755 --- a/docker-entrypoint.dev.sh +++ b/docker-entrypoint.dev.sh @@ -12,6 +12,5 @@ python -m manage loaddata doc_releases python -m manage loaddata dashboard_production_metrics # python -m manage loaddata dashboard_example_data python -m manage update_metrics -#python -m manage update_index exec "$@" diff --git a/docs/management/commands/update_docs.py b/docs/management/commands/update_docs.py index 785a406f3d..d1f3df0486 100644 --- a/docs/management/commands/update_docs.py +++ b/docs/management/commands/update_docs.py @@ -47,13 +47,6 @@ def add_arguments(self, parser): action="store_true", help="Ask before building each version", ) - parser.add_argument( - "--update-index", - action="store_true", - dest="update_index", - default=False, - help="Also update the search vector field.", - ) parser.add_argument( "--purge-cache", action="store_true", @@ -98,7 +91,6 @@ def _get_doc_releases(self, versions, options): def handle(self, *versions, **kwargs): self.verbosity = kwargs["verbosity"] - self.update_index = kwargs["update_index"] self.purge_cache = kwargs["purge_cache"] self.default_builders = ["json", "djangohtml"] @@ -106,17 +98,12 @@ def handle(self, *versions, **kwargs): # Keep track of which Git sources have been updated, e.g., # {'1.8': True} if the 1.8 docs updated. self.release_docs_changed = {} - # Only update the index if some docs rebuild. - self.update_index_required = False for release in self._get_doc_releases(versions, kwargs): self.build_doc_release( release, force=kwargs["force"], interactive=kwargs["interactive"] ) - if self.update_index_required: - call_command("update_index", **{"verbosity": self.verbosity}) - if self.purge_cache: changed_versions = { version @@ -172,8 +159,6 @@ def build_doc_release(self, release, force=False, interactive=False): ) return - self.update_index_required = self.update_index - source_dir = checkout_dir.joinpath("docs") if release.lang != "en": @@ -288,15 +273,6 @@ def zipfile_inclusion_filter(file_path): if release.is_default: self._setup_stable_symlink(release, built_dir) - # - # Rebuild the imported document list and search index. - # - if not self.update_index: - return - - if self.verbosity >= 2: - self.stdout.write(" reindexing...") - json_built_dir = parent_build_dir.joinpath("_built", "json") documents = gen_decoded_documents(json_built_dir) release.sync_to_db(documents) diff --git a/docs/management/commands/update_index.py b/docs/management/commands/update_index.py deleted file mode 100644 index 86d8080364..0000000000 --- a/docs/management/commands/update_index.py +++ /dev/null @@ -1,28 +0,0 @@ -import time - -from django.core.management.base import BaseCommand -from django.db import transaction - -from ...models import Document - - -class Command(BaseCommand): - - def handle(self, *args, **options): - """ - Update Document's search vector field in an atomic transaction. - - Inside an atomic transaction all not null search vector values are set - to null and than the field are updated using the document definition. - """ - _started_at = time.time() - with transaction.atomic(): - Document.objects.search_reset() - updated_documents = Document.objects.search_update() - elapsed = time.time() - _started_at - if options["verbosity"] >= 1: - self.stdout.write( - self.style.SUCCESS( - f"Indexed {updated_documents} documents in {elapsed:.03}s." - ) - ) diff --git a/docs/migrations/0007_add_docs_search_vector.py b/docs/migrations/0007_add_docs_search_vector.py new file mode 100644 index 0000000000..1834ef66f5 --- /dev/null +++ b/docs/migrations/0007_add_docs_search_vector.py @@ -0,0 +1,1658 @@ +# Generated by Django 5.2 on 2025-09-14 15:00 + +import django.contrib.postgres.indexes +import django.contrib.postgres.search +import django.db.models.fields.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("docs", "0006_alter_document_metadata_noop"), + ] + + operations = [ + migrations.RemoveIndex( + model_name="document", + name="docs_docume_search_5dc895_gin", + ), + migrations.RemoveField( + model_name="document", + name="search", + ), + migrations.AddField( + model_name="document", + name="search_vector", + field=models.GeneratedField( + db_persist=True, + expression=models.Case( + models.When( + config="arabic", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="arabic", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="arabic", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "arabic" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="arabic", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "arabic" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="arabic", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("arabic"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="arabic", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("arabic"), + ), + ), + models.When( + config="catalan", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="catalan", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="catalan", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "catalan" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="catalan", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "catalan" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="catalan", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("catalan"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="catalan", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("catalan"), + ), + ), + models.When( + config="danish", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="danish", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="danish", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "danish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="danish", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "danish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="danish", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("danish"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="danish", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("danish"), + ), + ), + models.When( + config="german", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="german", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="german", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "german" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="german", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "german" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="german", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("german"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="german", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("german"), + ), + ), + models.When( + config="greek", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="greek", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="greek", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "greek" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="greek", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "greek" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="greek", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("greek"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="greek", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("greek"), + ), + ), + models.When( + config="english", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="english", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="english", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "english" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="english", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "english" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="english", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("english"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="english", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("english"), + ), + ), + models.When( + config="spanish", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="spanish", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="spanish", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "spanish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="spanish", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "spanish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="spanish", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("spanish"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="spanish", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("spanish"), + ), + ), + models.When( + config="basque", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="basque", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="basque", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "basque" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="basque", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "basque" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="basque", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("basque"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="basque", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("basque"), + ), + ), + models.When( + config="finnish", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="finnish", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="finnish", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "finnish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="finnish", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "finnish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="finnish", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("finnish"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="finnish", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("finnish"), + ), + ), + models.When( + config="french", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="french", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="french", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "french" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="french", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "french" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="french", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("french"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="french", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("french"), + ), + ), + models.When( + config="irish", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="irish", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="irish", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "irish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="irish", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "irish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="irish", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("irish"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="irish", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("irish"), + ), + ), + models.When( + config="hindi", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="hindi", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="hindi", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "hindi" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="hindi", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "hindi" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="hindi", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("hindi"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="hindi", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("hindi"), + ), + ), + models.When( + config="hungarian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="hungarian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="hungarian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "hungarian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="hungarian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "hungarian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="hungarian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig( + "hungarian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="hungarian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("hungarian"), + ), + ), + models.When( + config="armenian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="armenian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="armenian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "armenian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="armenian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "armenian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="armenian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("armenian"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="armenian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("armenian"), + ), + ), + models.When( + config="indonesian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="indonesian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="indonesian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "indonesian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="indonesian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "indonesian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="indonesian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig( + "indonesian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="indonesian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("indonesian"), + ), + ), + models.When( + config="italian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="italian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="italian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "italian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="italian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "italian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="italian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("italian"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="italian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("italian"), + ), + ), + models.When( + config="lithuanian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="lithuanian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="lithuanian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "lithuanian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="lithuanian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "lithuanian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="lithuanian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig( + "lithuanian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="lithuanian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("lithuanian"), + ), + ), + models.When( + config="nepali", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="nepali", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="nepali", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "nepali" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="nepali", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "nepali" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="nepali", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("nepali"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="nepali", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("nepali"), + ), + ), + models.When( + config="dutch", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="dutch", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="dutch", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "dutch" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="dutch", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "dutch" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="dutch", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("dutch"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="dutch", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("dutch"), + ), + ), + models.When( + config="norwegian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="norwegian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="norwegian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "norwegian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="norwegian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "norwegian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="norwegian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig( + "norwegian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="norwegian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("norwegian"), + ), + ), + models.When( + config="portuguese", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="portuguese", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="portuguese", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "portuguese" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="portuguese", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "portuguese" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="portuguese", + weight="C", + ), + django.contrib.postgres.search.SearchConfig( + "portuguese" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="portuguese", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("portuguese"), + ), + ), + models.When( + config="romanian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="romanian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="romanian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "romanian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="romanian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "romanian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="romanian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("romanian"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="romanian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("romanian"), + ), + ), + models.When( + config="russian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="russian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="russian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "russian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="russian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "russian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="russian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("russian"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="russian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("russian"), + ), + ), + models.When( + config="serbian", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="serbian", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="serbian", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "serbian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="serbian", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "serbian" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="serbian", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("serbian"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="serbian", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("serbian"), + ), + ), + models.When( + config="swedish", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="swedish", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="swedish", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "swedish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="swedish", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "swedish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="swedish", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("swedish"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="swedish", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("swedish"), + ), + ), + models.When( + config="tamil", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="tamil", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="tamil", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "tamil" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="tamil", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "tamil" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="tamil", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("tamil"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="tamil", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("tamil"), + ), + ), + models.When( + config="turkish", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="turkish", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="turkish", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "turkish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="turkish", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "turkish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="turkish", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("turkish"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="turkish", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("turkish"), + ), + ), + models.When( + config="yiddish", + then=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="yiddish", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="yiddish", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "yiddish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="yiddish", + weight="B", + ), + django.contrib.postgres.search.SearchConfig( + "yiddish" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="yiddish", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("yiddish"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="yiddish", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("yiddish"), + ), + ), + default=django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.CombinedSearchVector( + django.contrib.postgres.search.SearchVector( + "title", config="simple", weight="A" + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "slug", "metadata" + ), + config="simple", + weight="A", + ), + django.contrib.postgres.search.SearchConfig( + "simple" + ), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "toc", "metadata" + ), + config="simple", + weight="B", + ), + django.contrib.postgres.search.SearchConfig("simple"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "body", "metadata" + ), + config="simple", + weight="C", + ), + django.contrib.postgres.search.SearchConfig("simple"), + ), + "||", + django.contrib.postgres.search.SearchVector( + django.db.models.fields.json.KeyTextTransform( + "parents", "metadata" + ), + config="simple", + weight="D", + ), + django.contrib.postgres.search.SearchConfig("simple"), + ), + ), + output_field=django.contrib.postgres.search.SearchVectorField(), + ), + ), + migrations.AlterField( + model_name="document", + name="config", + field=models.SlugField(db_default="simple", default="simple"), + ), + migrations.AddIndex( + model_name="document", + index=django.contrib.postgres.indexes.GinIndex( + fields=["search_vector"], name="document_search_vector_idx" + ), + ), + migrations.AddConstraint( + model_name="document", + constraint=models.CheckConstraint( + condition=models.Q( + ( + "config__in", + [ + "simple", + "arabic", + "catalan", + "danish", + "german", + "greek", + "english", + "spanish", + "basque", + "finnish", + "french", + "irish", + "hindi", + "hungarian", + "armenian", + "indonesian", + "italian", + "lithuanian", + "nepali", + "dutch", + "norwegian", + "portuguese", + "romanian", + "russian", + "serbian", + "swedish", + "tamil", + "turkish", + "yiddish", + ], + ) + ), + name="document_config_allowed_languages", + ), + ), + ] diff --git a/docs/models.py b/docs/models.py index fb6714b9bb..17c2cca01a 100644 --- a/docs/models.py +++ b/docs/models.py @@ -16,7 +16,11 @@ ) from django.core.cache import cache from django.db import models, transaction -from django.db.models import Q +from django.db.models import ( + Case, + Q, + When, +) from django.db.models.fields.json import KeyTextTransform from django.utils.functional import cached_property from django.utils.html import strip_tags @@ -27,10 +31,10 @@ from . import utils from .search import ( DEFAULT_TEXT_SEARCH_CONFIG, - DOCUMENT_SEARCH_VECTOR, START_SEL, STOP_SEL, TSEARCH_CONFIG_LANGUAGES, + get_document_search_vector, ) @@ -261,7 +265,7 @@ def search(self, query_text, release, document_category=None): search_query = SearchQuery( query_text, config=models.F("config"), search_type="websearch" ) - search_rank = SearchRank(models.F("search"), search_query) + search_rank = SearchRank(models.F("search_vector"), search_query) search = partial( SearchHeadline, start_sel=START_SEL, @@ -296,7 +300,7 @@ def search(self, query_text, release, document_category=None): ) vector_qs = ( base_qs.alias(rank=search_rank) - .filter(search=search_query) + .filter(search_vector=search_query) .order_by("-rank") ) if not vector_qs: @@ -314,22 +318,6 @@ def search(self, query_text, release, document_category=None): else: return self.none() - def search_reset(self): - """Set to null all not null Document's search vector fields.""" - return Document.objects.exclude(search=None).update(search=None) - - def search_update(self): - """ - Update Document's search vector fields using the document definition. - - This method don't index the module pages (since source code is hard to - combine with full text search) and the big flattened index of the CBVs. - """ - return Document.objects.exclude( - Q(path__startswith="_modules") - | Q(path__startswith="ref/class-based-views/flattened-index") - ).update(search=DOCUMENT_SEARCH_VECTOR) - class Document(models.Model): """ @@ -344,17 +332,42 @@ class Document(models.Model): path = models.CharField(max_length=500) title = models.CharField(max_length=500) metadata = models.JSONField(default=dict) - search = SearchVectorField(null=True, editable=False) - config = models.SlugField(default=DEFAULT_TEXT_SEARCH_CONFIG) + # Use Case/When to force the expression to be immutable, per: + # https://www.paulox.net/2025/09/08/djangocon-us-2025/ + search_vector = models.GeneratedField( + expression=Case( + *[ + When(config=lang, then=get_document_search_vector(lang)) + for lang in TSEARCH_CONFIG_LANGUAGES.values() + ], + default=get_document_search_vector(), + ), + output_field=SearchVectorField(), + db_persist=True, + ) + config = models.SlugField( + db_default=DEFAULT_TEXT_SEARCH_CONFIG, default=DEFAULT_TEXT_SEARCH_CONFIG + ) objects = DocumentQuerySet.as_manager() class Meta: + constraints = [ + models.CheckConstraint( + condition=Q( + config__in=[ + DEFAULT_TEXT_SEARCH_CONFIG, + *TSEARCH_CONFIG_LANGUAGES.values(), + ] + ), + name="document_config_allowed_languages", + ) + ] indexes = [ models.Index( fields=["release", "title"], name="document_release_title_idx" ), - GinIndex(fields=["search"]), + GinIndex(fields=["search_vector"], name="document_search_vector_idx"), ] unique_together = ("release", "path") diff --git a/docs/search.py b/docs/search.py index 1a2ebcaa70..3a99978d58 100644 --- a/docs/search.py +++ b/docs/search.py @@ -1,5 +1,5 @@ from django.contrib.postgres.search import SearchVector -from django.db.models import F, TextChoices +from django.db.models import TextChoices from django.db.models.fields.json import KeyTextTransform from django.utils.translation import gettext_lazy as _ @@ -40,15 +40,17 @@ # https://github.com/postgres/postgres/blob/REL_14_STABLE/src/bin/initdb/initdb.c#L2557 DEFAULT_TEXT_SEARCH_CONFIG = "simple" -DOCUMENT_SEARCH_VECTOR = ( - SearchVector("title", weight="A", config=F("config")) - + SearchVector(KeyTextTransform("slug", "metadata"), weight="A", config=F("config")) - + SearchVector(KeyTextTransform("toc", "metadata"), weight="B", config=F("config")) - + SearchVector(KeyTextTransform("body", "metadata"), weight="C", config=F("config")) - + SearchVector( - KeyTextTransform("parents", "metadata"), weight="D", config=F("config") + +def get_document_search_vector(lang=DEFAULT_TEXT_SEARCH_CONFIG): + """Return the search vector with the proper language config.""" + return ( + SearchVector("title", weight="A", config=lang) + + SearchVector(KeyTextTransform("slug", "metadata"), weight="A", config=lang) + + SearchVector(KeyTextTransform("toc", "metadata"), weight="B", config=lang) + + SearchVector(KeyTextTransform("body", "metadata"), weight="C", config=lang) + + SearchVector(KeyTextTransform("parents", "metadata"), weight="D", config=lang) ) -) + START_SEL = "" STOP_SEL = "" diff --git a/docs/tests/test_models.py b/docs/tests/test_models.py index 16f9028a11..d17bd4d051 100644 --- a/docs/tests/test_models.py +++ b/docs/tests/test_models.py @@ -7,7 +7,7 @@ from releases.models import Release -from ..models import DOCUMENT_SEARCH_VECTOR, Document, DocumentRelease +from ..models import Document, DocumentRelease class ModelsTests(TestCase): @@ -350,9 +350,6 @@ def setUpTestData(cls): ] Document.objects.bulk_create(Document(**doc) for doc in documents) - def setUp(self): - Document.objects.search_update() - def test_search(self): expected_list = [ ( @@ -415,29 +412,17 @@ def test_search_breadcrumbs(self): ], ) - def test_search_reset(self): - self.assertEqual(Document.objects.exclude(search=None).count(), 6) - self.assertEqual(Document.objects.search_reset(), 6) - self.assertEqual(Document.objects.exclude(search=None).count(), 0) - - def test_search_update(self): - self.assertEqual(Document.objects.exclude(search=None).count(), 6) - self.assertEqual(Document.objects.search_update(), 6) - self.assertEqual(Document.objects.exclude(search=None).count(), 6) - def test_search_highlight_stemmed(self): # The issue only manifests itself when the defaut search config is not english with connection.cursor() as cursor: cursor.execute("SET default_text_search_config TO 'simple'", []) - doc = self.release.documents.create( + self.release.documents.create( config="english", path="/", title="triaging tickets", metadata={"body": "text containing the word triaging", "breadcrumbs": []}, ) - doc.search = DOCUMENT_SEARCH_VECTOR - doc.save(update_fields=["search"]) self.assertQuerySetEqual( Document.objects.search("triaging", self.release), diff --git a/docs/tests/test_views.py b/docs/tests/test_views.py index fb5a94742d..1b5cb06e0d 100644 --- a/docs/tests/test_views.py +++ b/docs/tests/test_views.py @@ -195,7 +195,6 @@ def test_code_links(self): Document.objects.bulk_create( [Document(**queryset_data), Document(**empty_page_data)] ) - Document.objects.search_update() base_url = reverse_with_host( "document-detail", host="docs",