diff --git a/django_typesense/collections.py b/django_typesense/collections.py index 11060ca..2b43534 100644 --- a/django_typesense/collections.py +++ b/django_typesense/collections.py @@ -1,6 +1,5 @@ -import pdb - import django +import logging from typing import Iterable, Union, Dict, List @@ -16,6 +15,8 @@ from django_typesense.fields import TypesenseField, TypesenseCharField from django_typesense.typesense_client import client +logger = logging.getLogger(__name__) + _COLLECTION_META_OPTIONS = { 'schema_name', 'default_sorting_field', 'token_separators', 'symbols_to_index', 'query_by_fields' } @@ -196,9 +197,14 @@ def update_typesense_collection(self): """ Update the schema of an existing collection """ + try: + current_schema = self.retrieve_typesense_collection() + except ObjectNotFound: + self.create_typesense_collection() + current_schema = self.retrieve_typesense_collection() + self.create_or_update_synonyms() - current_schema = self.retrieve_typesense_collection() schema_changes = {} field_changes = [] @@ -222,6 +228,7 @@ def update_typesense_collection(self): schema_changes['fields'] = field_changes if not schema_changes: + logger.debug(f"No schema changes in {self.schema_name}") return return client.collections[self.schema_name].update(schema_changes) @@ -272,16 +279,25 @@ def create_or_update_synonyms(self): defined_synonyms.update(synonym_data) missing_synonyms_names = set(current_synonyms.keys()).difference(defined_synonyms.keys()) + has_changes = False for synonym_name in missing_synonyms_names: + has_changes = True self.delete_synonym(synonym_name) for synonym_name, synonym_data in defined_synonyms.items(): if synonym_name not in current_synonyms: + has_changes = True client.collections[self.schema_name].synonyms.upsert(synonym_name, synonym_data) elif synonym_data != current_synonyms[synonym_name]: + has_changes = True client.collections[self.schema_name].synonyms.upsert(synonym_name, synonym_data) + if has_changes: + logger.debug(f"Synonyms updated in {self.schema_name}") + else: + logger.debug(f"No synonyms to update in {self.schema_name}") + def get_synonyms(self) -> dict: """List all synonyms associated with this collection""" return client.collections[self.schema_name].synonyms.retrieve() diff --git a/django_typesense/management/__init__.py b/django_typesense/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django_typesense/management/commands/__init__.py b/django_typesense/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django_typesense/management/commands/updatecollections.py b/django_typesense/management/commands/updatecollections.py new file mode 100644 index 0000000..8917098 --- /dev/null +++ b/django_typesense/management/commands/updatecollections.py @@ -0,0 +1,45 @@ +import sys + +from django.core.management import BaseCommand +from django.apps import apps + + +class Command(BaseCommand): + help = "Create and/or Update Typesense Collections" + + def add_arguments(self, parser): + parser.add_argument( + "args", + metavar="collection_name", + nargs="*", + help="Specify the collection schema name(s) to create or update.", + ) + + def handle(self, *collection_names, **options): + collections = {} + for model_data in apps.all_models.values(): + for model in model_data.values(): + if hasattr(model, 'collection_class'): + collections[model.collection_class.schema_name] = model.collection_class + + collections_for_action = [] + # Make sure the collection name(s) they asked for exists + if collection_names := set(collection_names): + has_bad_names = False + + for collection_name in collection_names: + try: + collection = collections[collection_name] + except KeyError: + self.stderr.write(f"No collection exists with schema name '{collection_name}'") + has_bad_names = True + else: + collections_for_action.append(collection) + + if has_bad_names: + sys.exit(2) + else: + collections_for_action = collections.values() + + for collection in collections_for_action: + collection().update_typesense_collection()