# 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
    query = JSONField(
        help_text=_lazy("The raw ElasticSearch DSL query."), encoder=DjangoJSONEncoder
    )
    query_type = CharField(
        help_text=_lazy("Does this query return results, or just the hit count?"),
        choices=QueryType.choices,
        default=QueryType.SEARCH,
        max_length=10,
    )
    hits = JSONField(
        help_text=_lazy(
            "The list of meta info for each of the query matches returned."
        ),
        encoder=DjangoJSONEncoder,
    )
    total_hits = models.IntegerField(
        default=0,
        help_text=_lazy(
            "Total number of matches found for the query (!= the hits returned)."
        ),
    )
    total_hits_relation = models.CharField(
        max_length=3,
        default="",
        blank=True,
        choices=TotalHitsRelation.choices,
        help_text=_lazy(
            "Indicates whether this is an exact match ('eq') or a lower bound ('gte')"
        ),
    )

# 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

    query = JSONField(
        help_text=_lazy("The raw ElasticSearch DSL query."), encoder=DjangoJSONEncoder
    )
    query_type = CharField(
        help_text=_lazy("Does this query return results, or just the hit count?"),
        choices=QueryType.choices,
        default=QueryType.SEARCH,
        max_length=10,
    )
    hits = JSONField(
        help_text=_lazy(
            "The list of meta info for each of the query matches returned."
        ),
        encoder=DjangoJSONEncoder,
    )
    total_hits = models.IntegerField(
        default=0,
        help_text=_lazy(
            "Total number of matches found for the query (!= the hits returned)."
        ),
    )
    total_hits_relation = models.CharField(
        max_length=3,
        default="",
        blank=True,
        choices=TotalHitsRelation.choices,
        help_text=_lazy(
            "Indicates whether this is an exact match ('eq') or a lower bound ('gte')"
        ),
    )

    aggregations = JSONField(