# Path: elasticsearch_django/compat.py

# 
# Path: elasticsearch_django/settings.py
# def get_client(connection: str = "default") -> Elasticsearch:
#     """Return configured elasticsearch client."""
#     return Elasticsearch(get_connection_string(connection))
# 
# def get_model_index_properties(instance: Model, index: str) -> list[str]:
#     """Return the list of properties specified for a model in an index."""
#     mapping = get_index_mapping(index)
#     return list(mapping["mappings"]["properties"].keys())
# 
# def get_model_indexes(model: Model) -> list[str]:
#     """
#     Return list of all indexes in which a model is configured.
# 
#     A model may be configured to appear in multiple indexes. This function
#     will return the names of the indexes as a list of strings. This is
#     useful if you want to know which indexes need updating when a model
#     is saved.
# 
#     Args:
#         model: a Django model class.
# 
#     """
#     indexes = []  # type: List[str]
#     for index in get_index_names():
#         for app_model in get_index_models(index):
#             if app_model == model:
#                 indexes.append(index)
#     return indexes
# 
# def get_setting(key, *default: str | int | bool | list | dict) -> SettingType:
#     """Return specific search setting from Django conf."""
#     if default:
#         return get_settings().get(key, default[0])
#     else:
#         return get_settings()[key]


import logging
import time
from typing import TYPE_CHECKING, Any, cast
from django.conf import settings
from django.core.cache import cache
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.db.models.expressions import RawSQL
from django.db.models.fields import CharField
from django.db.models.query import QuerySet
from django.utils.timezone import now as tz_now
from django.utils.translation import gettext_lazy as _lazy
from elasticsearch_dsl import Search
from .compat import JSONField
from .settings import (
    get_client,
    get_model_index_properties,
    get_model_indexes,
    get_setting,
)
    from django.contrib.auth.models import AbstractBaseUser
        if new_doc == cached_doc:
            logger.debug("Search document for %r is unchanged, ignoring update.", self)
            return
        cache.set(cache_key, new_doc, timeout=get_setting("cache_expiry", 60))
        get_client().index(index=index, body=new_doc, id=self.pk)  # type: ignore

    def update_search_document(self, *, index: str, update_fields: list[str]) -> None:
        """
        Partial update of a document in named index.

        Partial updates are invoked via a call to save the document
        with 'update_fields'. These fields are passed to the
        as_search_document method so that it can build a partial
        document. NB we don't just call as_search_document and then
        strip the fields _not_ in update_fields as we are trying
        to avoid possibly expensive operations in building the
        source document. The canonical example for this method
        is updating a single timestamp on a model - we don't want
        to have to walk the model relations and build a document
        in this case - we just want to push the timestamp.

        When POSTing a partial update the `as_search_document` doc
        must be passed to the `client.update` wrapped in a "doc" node,
        # noqa: E501, see: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html

        """
        doc = self.as_search_document_update(index=index, update_fields=update_fields)
        if not doc:
            logger.debug("Ignoring object update as document is empty.")
            return

# Path: elasticsearch_django/compat.py

# 
# Path: elasticsearch_django/settings.py
# def get_client(connection: str = "default") -> Elasticsearch:
#     """Return configured elasticsearch client."""
#     return Elasticsearch(get_connection_string(connection))
# 
# def get_model_index_properties(instance: Model, index: str) -> list[str]:
#     """Return the list of properties specified for a model in an index."""
#     mapping = get_index_mapping(index)
#     return list(mapping["mappings"]["properties"].keys())
# 
# def get_model_indexes(model: Model) -> list[str]:
#     """
#     Return list of all indexes in which a model is configured.
# 
#     A model may be configured to appear in multiple indexes. This function
#     will return the names of the indexes as a list of strings. This is
#     useful if you want to know which indexes need updating when a model
#     is saved.
# 
#     Args:
#         model: a Django model class.
# 
#     """
#     indexes = []  # type: List[str]
#     for index in get_index_names():
#         for app_model in get_index_models(index):
#             if app_model == model:
#                 indexes.append(index)
#     return indexes
# 
# def get_setting(key, *default: str | int | bool | list | dict) -> SettingType:
#     """Return specific search setting from Django conf."""
#     if default:
#         return get_settings().get(key, default[0])
#     else:
#         return get_settings()[key]


# Path: elasticsearch_django/models.py
import logging
import time
from typing import TYPE_CHECKING, Any, cast
from django.conf import settings
from django.core.cache import cache
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.db.models.expressions import RawSQL
from django.db.models.fields import CharField
from django.db.models.query import QuerySet
from django.utils.timezone import now as tz_now
from django.utils.translation import gettext_lazy as _lazy
from elasticsearch_dsl import Search
from .compat import JSONField
from .settings import (
    get_client,
    get_model_index_properties,
    get_model_indexes,
    get_setting,
)
    from django.contrib.auth.models import AbstractBaseUser

        if new_doc == cached_doc:
            logger.debug("Search document for %r is unchanged, ignoring update.", self)
            return
        cache.set(cache_key, new_doc, timeout=get_setting("cache_expiry", 60))
        get_client().index(index=index, body=new_doc, id=self.pk)  # type: ignore

    def update_search_document(self, *, index: str, update_fields: list[str]) -> None:
        """
        Partial update of a document in named index.

        Partial updates are invoked via a call to save the document
        with 'update_fields'. These fields are passed to the
        as_search_document method so that it can build a partial
        document. NB we don't just call as_search_document and then
        strip the fields _not_ in update_fields as we are trying
        to avoid possibly expensive operations in building the
        source document. The canonical example for this method
        is updating a single timestamp on a model - we don't want
        to have to walk the model relations and build a document
        in this case - we just want to push the timestamp.

        When POSTing a partial update the `as_search_document` doc
        must be passed to the `client.update` wrapped in a "doc" node,
        # noqa: E501, see: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html

        """
        doc = self.as_search_document_update(index=index, update_fields=update_fields)
        if not doc:
            logger.debug("Ignoring object update as document is empty.")
            return

        retry_on_conflict = cast(int, get_setting("retry_on_conflict", 0))