
    Q
i^N                       d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z" d dl#m$Z$ d d	l%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, d d
l-m.Z.m/Z/m0Z0 d dl1m2Z2m3Z3m4Z4 e	rd dl5m6Z6 d dl7m8Z8 d dl9m:Z: d dl!m;Z; d dlm<Z= d dl>m?Z? d dl@mAZA  e=jB        d          rd dlCmDZD nd dlEmDZD d dl9m:Z: d dlFmGZGmHZHmIZImJZJmKZK d dlLmMZMmNZNmOZO d dlPmQZQm;Z;mRZRmSZSmTZTmUZU d dlVmWZW d dlXmYZY d dlZm[Z[m\Z\m]Z]m^Z^ d dl_m`Z` d dlambZbmcZc d dldmeZemfZfmgZgmhZh d dlimjZj  ejek          ZldZmd d!d"d#d!d"gZneeeeoe;f         eeeoeeoepeqerf         f         df         f         eeoe;f         f         Zsd$d%d&e;d'ebd(eeeoe
f                  fd)Ztd$d*d&eQd+ecd(eeeoe
f                  fd,Zu G d- d.          Zv G d/ d0ev          Zw G d1 d2ev          ZxdS )3    N)ceil)TYPE_CHECKINGAnyAsyncGeneratorCallableDict	GeneratorIterableListOptionalSequenceTupleUnioncast)Redis)RedisClusterHybridQuery)VectorQuery)SQLQuery)_keys_share_hash_tagasync_cluster_create_indexasync_cluster_searchcluster_create_indexcluster_searchconvert_bytes	make_dict)AsyncRedisClientSyncRedisClientSyncRedisCluster)deprecated_argumentdeprecated_functionsync_wrapper)AggregateResult)Document)Result)	BaseQuery)__version__)NEVER_DECODE)get_protocol_version5)IndexDefinition)QueryValidationErrorRedisModuleVersionErrorRedisSearchErrorRedisVLErrorSchemaValidationError)BaseStorageHashStorageJsonStorage)AggregationQueryr'   BaseVectorQuery
CountQueryFilterQuery	TextQuery)AggregateHybridQuery)FilterExpression)RedisConnectionFactoryconvert_index_info_to_schemasupports_svssupports_svs_async)SVS_MIN_REDIS_VERSION)IndexSchemaStorageType)VECTOR_NORM_MAPSVSVectorFieldVectorDistanceMetricVectorIndexAlgorithm)
get_loggerz`Hybrid search is not available in this version of redis-py. Please upgrade to redis-py >= 7.1.0.searchiJQ  )nameversearchlightresultsr&   queryschemareturnc                 <   t          t                    r| j        S |j        j        t
          j        k    ot          t                    oj         t          t                    ryj
        rrt          |j        j                 j        j                                                  }|t          j        k    rt%          j        d           t(          |j                 nddddt,          t.          t0          f         ffdfd| j        D             S )a  Convert a list of search Result objects into a list of document
    dictionaries.

    This function processes results from Redis, handling different storage
    types and query types. For JSON storage with empty return fields, it
    unpacks the JSON object while retaining the document ID. The 'payload'
    field is also removed from all resulting documents for consistency.

    Args:
        results (Result): The search results from Redis.
        query (BaseQuery): The query object used for the search.
        storage_type (StorageType): The storage type of the search
            index (json or hash).

    Returns:
        List[Dict[str, Any]]: A list of processed document dictionaries.
    zAttempting to normalize inner product distance metric. Use cosine distance instead which is normalized inner product by definition.Ndocr%   rO   c                    | j         }rd|v r|                    di           }t          |t                    rt	          j        |          }t          |t                    rd|                    d          i|S t          d|           r8t           t          |j	                                               |j	        <   |
                    dd            |S )Njsonidz%Unable to parse json data from Redis payload)__dict__get
isinstancestrrS   loadsdict
ValueErrorfloatDISTANCE_IDpop)rQ   doc_dict	json_datanorm_fnrM   unpack_jsons      C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\redisvl/index/index.py_processz!process_results.<locals>._process   s    <  	R6X-- VR00I)S)) 2 Jy11	)T** ?hll400>I>>PYPPQQQ 	*-hu'89::;;+ +HU&'
 	Y%%%    c                 &    g | ]} |          S  rh   ).0rQ   re   s     rd   
<listcomp>z#process_results.<locals>.<listcomp>   s!    222cHHSMM222rf   )rX   r7   totalindexstorage_typerB   JSONr8   _return_fieldsr6   _normalize_vector_distancerE   fields_vector_field_nameattrsdistance_metricupperIPwarningswarnrC   valuer   rY   r   docs)rL   rM   rN   dist_metricre   rb   rc   s    `  @@@rd   process_resultsr|   |   sB   * %$$ } 
	"k&6	6 	%uk**	%$$  	5/** 0P *M%239IOOQQ
 
 .111M V   "+"34j T#s(^        . 3222W\2222rf   r$   rm   c                 0    d fd| j         D             S )a  Convert an aggregate result object into a list of document dictionaries.

    This function processes results from Redis, handling different storage
    types and query types. For JSON storage with empty return fields, it
    unpacks the JSON object while retaining the document ID. The 'payload'
    field is also removed from all resulting documents for consistency.

    Args:
        results (AggregateResult): The aggregate results from Redis.
        query (AggregationQuery): The aggregation query object used for the aggregation.
        storage_type (StorageType): The storage type of the search
            index (json or hash).

    Returns:
        List[Dict[str, Any]]: A list of processed document dictionaries.
    c                 j    t          t          |                     }|                    dd            |S )N__score)r   r   r_   )rowresults     rd   re   z+process_aggregate_results.<locals>._process   s0    =--..

9d###rf   c                 &    g | ]} |          S rh   rh   )ri   rre   s     rd   rj   z-process_aggregate_results.<locals>.<listcomp>   s!    ...AHHQKK...rf   )rows)rL   rM   rm   re   s      @rd   process_aggregate_resultsr      s0    (  
 /.......rf   c                      e Zd ZU dZej        eej        eiZ	e
ed<   d Zedefd            ZdefdZdeddfd	Zdeddfd
Zedefd            Zedefd            Zedee         fd            Zedefd            Zedefd            Zedefd            Zedeeef         fd            Z d Z!dedefdZ"defdZ#dS )BaseSearchIndexzBase search engine classrN   c                      d S Nrh   )argskwargss     rd   __init__zBaseSearchIndex.__init__   s    rf   rO   c                 X     | j         | j        j        j                 | j                  S )z&The storage type for the index schema.)index_schema)_STORAGE_MAPrN   rl   rm   selfs    rd   _storagezBaseSearchIndex._storage   s3     At !2!?@
 
 
 	
rf   c                 l    t          d | j        j                                        D                       S )z6Check if schema contains any SVS-VAMANA vector fields.c              3   @   K   | ]}t          |t                    V  d S r   )rX   rD   )ri   fields     rd   	<genexpr>z3BaseSearchIndex._uses_svs_vamana.<locals>.<genexpr>   s=       
 
27Jun--
 
 
 
 
 
rf   )anyrN   rq   valuesr   s    rd   _uses_svs_vamanaz BaseSearchIndex._uses_svs_vamana   sA     
 
;?;;M;T;T;V;V
 
 
 
 
 	
rf   rM   Nc                    t          |t                    rG| j        j        |j                 }|j        r)|j        j        t          j	        k    rt          d          t          |t          t          f          r{| j        j        j        }|j        }|ct          |          dk    rRt          |          dk    rAt          |t                    rdnd}t!          j        d| dt$          d	           dS dS dS dS dS )
zValidate a query.zPVector field using 'flat' algorithm does not support EF_RUNTIME query parameter.Nr   r9   r:   ag  Query-time stopwords are configured but the index has STOPWORDS 0 (stopwords = []). This is counterproductive: all words including common words like 'of', 'the', 'a' are indexed, but your query-time stopwords will filter them from the search query. This makes your search less precise than it could be. Consider setting stopwords=None (or any falsy value) in z! to search for all indexed words.   )
stacklevel)rX   r   rN   rq   rr   
ef_runtimers   	algorithmrF   HNSWr-   r9   r:   rl   	stopwordslenrw   rx   UserWarning)r   rM   r   index_stopwordsquery_stopwords
query_types         rd   _validate_queryzBaseSearchIndex._validate_query   s?   e[)) 	K&u'?@E EK$9=Q=V$V$V*f  
 ei)=>?? 	"k/9O#oO  +((A--((1,, "%330KK/ 
 } PZ	} } }
        #	 	 ,+--,,rf   c                     	 ddl m} ddlm} n)# t          t
          f$ r t	          t                    w xY wt          ||          st          dt          |                     dS )z-Validate that a hybrid query can be executed.r   )HybridResultr   z'query must be of type HybridQuery, got N)
#redis.commands.search.hybrid_resultr   redisvl.query.hybridr   ImportErrorModuleNotFoundError_HYBRID_SEARCH_ERROR_MESSAGErX   	TypeErrortype)r   rM   r   r   s       rd   _validate_hybrid_queryz&BaseSearchIndex._validate_hybrid_query  s    	<HHHHHH888888801 	< 	< 	<:;;;	< %-- 	USd5kkSSTTT	U 	Us    &5c                 $    | j         j        j        S )z#The name of the Redis search index.)rN   rl   rI   r   s    rd   rI   zBaseSearchIndex.name*  s     { %%rf   c                 b    | j         j        j        }t          |t                    r|d         n|S )zpThe key prefix used in forming Redis keys.

        For multi-prefix indexes, returns the first prefix.
        r   rN   rl   prefixrX   listr   r   s     rd   r   zBaseSearchIndex.prefix/  s.     ")&vt44@vayy&@rf   c                 X    | j         j        j        }t          |t                    r|n|gS )z+All key prefixes configured for this index.r   r   s     rd   prefixeszBaseSearchIndex.prefixes8  s,     ")#FD11?vvx?rf   c                 $    | j         j        j        S )z]The optional separator between a defined prefix and key value in
        forming a Redis key.)rN   rl   key_separatorr   s    rd   r   zBaseSearchIndex.key_separator>  s     { ..rf   c                 $    | j         j        j        S )zNThe underlying storage type for the search index; either
        hash or json.)rN   rl   rm   r   s    rd   rm   zBaseSearchIndex.storage_typeD  s     { --rf   schema_pathc                 >    t          j        |          } | dd|i|S )a  Create a SearchIndex from a YAML schema file.

        Args:
            schema_path (str): Path to the YAML schema file.

        Returns:
            SearchIndex: A RedisVL SearchIndex object.

        .. code-block:: python

            from redisvl.index import SearchIndex

            index = SearchIndex.from_yaml("schemas/schema.yaml", redis_url="redis://localhost:6379")
        rN   rh   )rA   	from_yaml)clsr   r   rN   s       rd   r   zBaseSearchIndex.from_yamlJ  s/      &{33s++&+F+++rf   schema_dictc                 >    t          j        |          } | dd|i|S )a  Create a SearchIndex from a dictionary.

        Args:
            schema_dict (Dict[str, Any]): A dictionary containing the schema.

        Returns:
            SearchIndex: A RedisVL SearchIndex object.

        .. code-block:: python

            from redisvl.index import SearchIndex

            index = SearchIndex.from_dict({
                "index": {
                    "name": "my-index",
                    "prefix": "rvl",
                    "storage_type": "hash",
                },
                "fields": [
                    {"name": "doc-id", "type": "tag"}
                ]
            }, redis_url="redis://localhost:6379")

        rN   rh   )rA   	from_dict)r   r   r   rN   s       rd   r   zBaseSearchIndex.from_dict]  s/    4 &{33s++&+F+++rf   c                      t          d          )#Disconnect from the Redis database.z0This method should be implemented by subclasses.)NotImplementedErrorr   s    rd   
disconnectzBaseSearchIndex.disconnectz  s    !"TUUUrf   rT   c                 d    | j                             || j        | j        j        j                  S )a  Construct a redis key as a combination of an index key prefix (optional)
        and specified id.

        The id is typically either a unique identifier, or
        derived from some domain-specific metadata combination (like a document
        id or chunk id).

        Args:
            id (str): The specified unique identifier for a particular
                document indexed in Redis.

        Returns:
            str: The full Redis key including key prefix and value as a string.
        )rT   r   r   )r   _keyr   rN   rl   r   )r   rT   s     rd   keyzBaseSearchIndex.key~  s6     }!!;++9 " 
 
 	
rf   c                 j    t          |           j         d| j        d| j        d| j        j        dS )Nz(name=z, prefixes=z, storage_type=))r   __name__rI   r   rm   ry   r   s    rd   __repr__zBaseSearchIndex.__repr__  sQ    Dzz" 9 9$) 9 9$- 9 9 -39 9 9	
rf   )$r   
__module____qualname____doc__rB   HASHr3   rn   r4   r   rA   __annotations__r   propertyr2   r   boolr   r'   r   r   r   rY   rI   r   r   r   r   rm   classmethodr   r   r   r   r   r   rh   rf   rd   r   r      sU        "" 	++L
    
+ 
 
 
 X

$ 
 
 
 
#Y #4 # # # #J
UC 
UD 
U 
U 
U 
U &c & & & X& A A A A XA @$s) @ @ @ X@
 /s / / / X/
 .k . . . X.
 ,C , , , [,$ ,DcN , , , [,8V V V
c 
c 
 
 
 
*
# 
 
 
 
 
 
rf   r   c                   b   e Zd ZdZ edd          	 	 	 	 dFdedee         dee         d	ee	ee
f                  d
ef
d            Zd Ze	 	 dGdedee         dee         fd            Zedee         fd            Zedefd            Z edd          dHdee         fd            Z edd          defd            ZdIdZdJdededdfdZdKdefdZdee         defdZdefdZd eeee         f         defd!Zd"eeee         f         defd#Zd eeee         f         d$edeeee         f         fd%Z 	 	 	 	 	 dLd&e!e
         d'ee         d ee!e                  d$ee         d(ee"         d)ee         dee         fd*Z#d+edee	ee
f                  fd,Z$d-e%dee	ee
f                  fd.Z&d/e'dee	ee
f                  fd0Z(dMd2Z)	 dNd4ee*         d)eded5         fd6Z+dOd7Z,d8e-dee	ee
f                  fd9Z.	 dNd4e/e0         d)edeee	ee
f                           fd:Z1d8e0dee	ee
f                  fd;Z2d8ee0e%e-e'f         dee	ee
f                  fd<Z3dPd8e0d>ede4fd?Z5dee         fd@Z6defdAZ7e8dedede	ee
f         fdB            Z9dHdee         de	ee
f         fdCZ:dD Z;dE Z<dS )QSearchIndexa  A search index class for interacting with Redis as a vector database.

    The SearchIndex is instantiated with a reference to a Redis database and an
    IndexSchema (YAML path or dictionary object) that describes the various
    settings and field configurations.

    .. code-block:: python

        from redisvl.index import SearchIndex

        # initialize the index object with schema from file
        index = SearchIndex.from_yaml(
            "schemas/schema.yaml",
            redis_url="redis://localhost:6379",
            validate_on_load=True
        )

        # create the index
        index.create(overwrite=True, drop=False)

        # data is an iterable of dictionaries
        index.load(data)

        # delete index and data
        index.delete(drop=True)

    connection_argsUse connection_kwargs instead.NFrN   redis_client	redis_urlconnection_kwargsvalidate_on_loadc                    d|v r|                     d          }t          |t                    st          d          || _        || _        |                     dd          | _        || _        || _        |pi | _	        t          j                    | _        |                     dd          | _        |du | _        | j        rt          j        | | j                   dS dS )a  Initialize the RedisVL search index with a schema, Redis client
        (or URL string with other connection args), connection_args, and other
        kwargs.

        Args:
            schema (IndexSchema): Index schema object.
            redis_client(Optional[Redis]): An
                instantiated redis client.
            redis_url (Optional[str]): The URL of the Redis server to
                connect to.
            connection_kwargs (Dict[str, Any], optional): Redis client connection
                args.
            validate_on_load (bool, optional): Whether to validate data against schema
                when loading. Defaults to False.
        r   'Must provide a valid IndexSchema objectlib_nameN_client_validatedF)r_   rX   rA   r\   rN   _validate_on_load	_lib_name_SearchIndex__redis_client
_redis_url_connection_kwargs	threadingLock_lock_validated_client_owns_redis_clientweakreffinalizer   )r   rN   r   r   r   r   r   s          rd   r   zSearchIndex.__init__  s    2 && &

+< = =&+.. 	HFGGG!1(.

:t(D(D +#"3"9r^%%
!',?!G!G".$"6" 	4T4?33333	4 	4rf   c                     | j         du rt                              d           dS | j        r| j                                         d| _        dS )r   Fz,Index does not own client, not disconnectingN)r   loggerinfor   closer   s    rd   r   zSearchIndex.disconnect  sV    "e++KKFGGGF 	(%%'''"rf   rI   c                    |rt          j        dd|i|}n|rt          j        |           d|d<   |st          d          |                     ||          }t          |          }t          j        |          } | ||fi |S )a  
        Initialize from an existing search index in Redis by index name.

        Args:
            name (str): Name of the search index in Redis.
            redis_client(Optional[Redis]): An
                instantiated redis client.
            redis_url (Optional[str]): The URL of the Redis server to
                connect to.

        Raises:
            ValueError: If redis_url or redis_client is not provided.
        r   Tr   z/Must provide either a redis_url or redis_clientrh   )r<   get_redis_connectionvalidate_sync_redisr\   _infor=   rA   r   r   rI   r   r   r   
index_infor   rN   s           rd   from_existingzSearchIndex.from_existing  s    *  		/1F  # LL  	/"6|DDD*.F&' 	PNOOO YYt\22
2:>>&{33s6<226222rf   rO   c                     | j         S z&The underlying redis-py client object.)r   r   s    rd   clientzSearchIndex.client  s     ""rf   c                 @   | j         ]| j        5  | j         7i | j        }| j        r
| j        |d<   t	          j        dd| j        i|| _         ddd           n# 1 swxY w Y   | j        s-| j        r&t	          j        | j         | j                   d| _        | j         S )zs
        Get a Redis client instance.

        Lazily creates a Redis client instance if it doesn't exist.
        Nr   r   Trh   )	r   r   r   r   r<   r   r   r   r   r   r   s     rd   _redis_clientzSearchIndex._redis_client  s    & 	 	&.8 78F~ <-1^z**@*U + +"&/+ + +D'	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 % 	*$. 	*"6#   &*D"""s   ?AA!Aconnect'Pass connection parameters in __init__.c                 6    t          j        dd|i|| _        dS )a  Connect to a Redis instance using the provided `redis_url`, falling
        back to the `REDIS_URL` environment variable (if available).

        Note: Additional keyword arguments (`**kwargs`) can be used to provide
        extra options specific to the Redis connection.

        Args:
            redis_url (Optional[str], optional): The URL of the Redis server to
                connect to.

        Raises:
            redis.exceptions.ConnectionError: If the connection to the Redis
                server fails.
            ValueError: If the Redis URL is not provided nor accessible
                through the `REDIS_URL` environment variable.
            ModuleNotFoundError: If required Redis modules are not installed.
        r   Nrh   )r<   r   r   )r   r   r   s      rd   r   zSearchIndex.connect7  s4    & 5I 
 

#)
 
rf   
set_clientc                 <    t          j        |           || _        | S )a  Manually set the Redis client to use with the search index.

        This method configures the search index to use a specific Redis or
        Async Redis client. It is useful for cases where an external,
        custom-configured client is preferred instead of creating a new one.

        Args:
            redis_client (Redis): A Redis or Async Redis
                client instance to be used for the connection.

        Raises:
            TypeError: If the provided client is not valid.
        )r<   r   r   )r   r   r   s      rd   r  zSearchIndex.set_clientN  s"     	2<@@@*rf   c                 `    t          | j                  st          j        t                    dS zValidate SVS-VAMANA support.

        Raises:
            RedisModuleVersionError: If SVS-VAMANA requirements are not met.
        N)r>   r   r.   for_svs_vamanar@   r   s    rd   _check_svs_supportzSearchIndex._check_svs_supporta  s6     D.// 	P)89NOOO	P 	Prf   	overwritedropc           	      P   | j         j        }|st          d          t          |t                    st          d          |                                 r|                                  |                                 rN|st          
                    d           dS t          
                    d           |                     |           	 | j         j        j        }t          |t                    r|n|g}t          || j        j                  }| j         j        j        }t          | j        t(                    r t+          | j        | j        |||           dS | j                            | j                                      |||	           dS # t2          j        j        $ r-}t9          d
| j         dt;          |                     |d}~wt<          $ rG}t                              d           t9          d| j         dt;          |                     |d}~ww xY w)a  Create an index in Redis with the current schema and properties.

        Args:
            overwrite (bool, optional): Whether to overwrite the index if it
                already exists. Defaults to False.
            drop (bool, optional): Whether to drop all keys associated with the
                index in the case of overwriting. Defaults to False.

        Raises:
            RuntimeError: If the index already exists and 'overwrite' is False.
            ValueError: If no fields are defined for the index.

        .. code-block:: python

            # create an index in Redis; only if one does not exist with given name
            index.create()

            # overwrite an index in Redis without dropping associated data
            index.create(overwrite=True)

            # overwrite an index in Redis; drop associated data (clean slate)
            index.create(overwrite=True, drop=True)
        No fields defined for indexoverwrite must be of type bool&Index already exists, not overwriting.N"Index already exists, overwriting.)r	  r   
index_type
index_namer   rq   
definitionr   rq   r  r   Failed to create index '' on Redis: &Error while trying to create the index!Unexpected error creating index '': ) rN   redis_fieldsr\   rX   r   r   r   r  existsr   r   deleterl   r   r   r,   r   r   r   r   r   r   rI   ftcreate_indexredis
exceptions
RedisErrorr/   rY   	Exception	exception)	r   r  r	  r  r   prefix_listr  r   es	            rd   createzSearchIndex.createj  sa   2 {/ 	<:;;;)T** 	><===   "" 	&##%%%;;== 	# DEEEtKK<===KKTK""" 	[&-F$.vt$<$<J&&6(K("t}/A  J )3I$,l;; $#y-')'      "%%di00==')' >     
 * 	 	 	"J49JJ#a&&JJ   	 	 	EFFF"JDIJJ#a&&JJ 	s,   BF 5F H%)(GH%AH  H%Tc                    	 |rBt          | j        t                    r(|                                  d| j        j        j        g}n*d| j        j        j        g}|r|                    d           t          | j        t                    r.| j                                        g} | j        j	        |d|i dS  | j        j	        |  dS # t          $ r%}t          dt          |                     |d}~ww xY w)aC  Delete the search index while optionally dropping all keys associated
        with the index.

        Args:
            drop (bool, optional): Delete the key / documents pairs in the
                index. Defaults to True.

        raises:
            redis.exceptions.ResponseError: If the index does not exist.
        FT.DROPINDEXDDtarget_nodesError while deleting index: N)rX   r   r   clearrN   rl   rI   appendget_default_nodeexecute_commandr"  r/   rY   )r   r	  cmd_argsr*  r%  s        rd   r  zSearchIndex.delete  s   	S  	*
4#5|DD 	*

*DK,=,BC +DK,=,BC *OOD)))$,l;; > $ 2 C C E EF2"2HX<XXXXX2"2H==== 	S 	S 	S"#J#a&&#J#JKKQRR	Ss   B4C	 8C	 	
C8 C33C8
batch_keysc                    t          t          | j                  }t          |t                    }|rud}|D ]o}	 |t          t
          |                    |                    z  }/# t          j        j	        $ r*}t                              d| d|            Y d}~hd}~ww xY wnt          t
           |j        |           }|S )  Delete a batch of keys from Redis.

        For Redis Cluster, keys are deleted individually due to potential
        cross-slot limitations. For standalone Redis, keys are deleted in
        a single operation for better performance.

        Args:
            batch_keys (List[str]): List of Redis keys to delete.

        Returns:
            int: Count of records deleted from Redis.
        r   Failed to delete key : N)r   r   r   rX   r   intr  r  r   r!  r   warningr   r1  r   
is_clusterrecords_deleted_in_batchkey_to_deleter%  s          rd   _delete_batchzSearchIndex._delete_batch  s     ot'9::55
 	M'($!+ Q QQ,S&--:V:V0W0WW,,'2 Q Q QNN#O=#O#OA#O#OPPPPPPPPQQ (,C
1K'L'L$''s   +A%%B#9 BB#c                 ^   d}d}|                                  }t          |d         |z            }d}t          t          d          dg          }|                    d|           	 |                     |          }|r+||k    r%d	 |D             }||                     |          z  }nnD|S )
a  Clear all keys in Redis associated with the index, leaving the index
        available and in-place for future insertions or updates.

        NOTE: This method requires custom behavior for Redis Cluster because
        here, we can't easily give control of the keys we're clearing to the
        user so they can separate them based on hash tag.

        Returns:
            int: Count of records deleted from Redis.
          )\(?num_docsr   *rT   return_fieldsTc                     g | ]
}|d          S rT   rh   ri   records     rd   rj   z%SearchIndex.clear.<locals>.<listcomp>
      ???vfTl???rf   r   r   r8   r;   paging_queryr<  	r   
batch_size	max_ratior   max_records_deletedtotal_records_deletedrM   batchr1  s	            rd   r,  zSearchIndex.clear  s     
	yy{{"y(
 
 &',S11$HHHQ
###	KK&&E .2EEE?????
%););J)G)GG%%	 %$rf   keysc                 ~    t          |t                    r | j        j        | S | j                            |          S )Remove a specific entry or entries from the index by it's key ID.

        Args:
            keys (Union[str, List[str]]): The document ID or IDs to remove from the index.

        Returns:
            int: Count of records deleted from Redis.
        )rX   r   r   r  )r   rR  s     rd   	drop_keyszSearchIndex.drop_keys  s@     dD!! 	3,4%,d33%,,T222rf   idsc                 >    t          |t                    rY|sdS  fd|D             }t           j        t                    rt	          |          st          d            j        j        | S                      |          } j                            |          S )4  Remove documents from the index by their document IDs.

        This method converts document IDs to Redis keys automatically by applying
        the index's key prefix and separator configuration.

        NOTE: Cluster users will need to incorporate hash tags into their
        document IDs and only call this method with documents from a single hash
        tag at a time.

        Args:
            ids (Union[str, List[str]]): The document ID or IDs to remove from the index.

        Returns:
            int: Count of documents deleted from Redis.
        r   c                 :    g | ]}                     |          S rh   r   ri   rT   r   s     rd   rj   z.SearchIndex.drop_documents.<locals>.<listcomp>2  #    ///RDHHRLL///rf   8All keys must share a hash tag when using Redis Cluster.)rX   r   r   r   r   r\   r  r   )r   rV  rR  r   s   `   rd   drop_documentszSearchIndex.drop_documents  s      c4   	2 q////3///D"L  *400 !N   -4%,d33((3--C%,,S111rf   ttlc                     t          |t                    rH| j                                        }|D ]}|                    ||           |                                S | j                            ||          S )Set the expiration time for a specific entry or entries in Redis.

        Args:
            keys (Union[str, List[str]]): The entry ID or IDs to set the expiration for.
            ttl (int): The time-to-live in seconds.
        )rX   r   r   pipelineexpireexecute)r   rR  r_  piper   s        rd   expire_keyszSearchIndex.expire_keys?  sw     dD!! 	8%..00D & &C%%%%<<>>!%,,T3777rf   dataid_field
preprocessrM  c           
      D   	 | j                             | j        ||||||| j                  S # t          $ r }t
                              d            d}~wt          $ r?}t
                              d           t          dt          |                     |d}~ww xY w)ar  Load objects to the Redis database. Returns the list of keys loaded
        to Redis.

        RedisVL automatically handles constructing the object keys, batching,
        optional preprocessing steps, and setting optional expiration
        (TTL policies) on keys.

        Args:
            data (Iterable[Any]): An iterable of objects to store.
            id_field (Optional[str], optional): Specified field used as the id
                portion of the redis key (after the prefix) for each
                object. Defaults to None.
            keys (Optional[Iterable[str]], optional): Optional iterable of keys.
                Must match the length of objects if provided. Defaults to None.
            ttl (Optional[int], optional): Time-to-live in seconds for each key.
                Defaults to None.
            preprocess (Optional[Callable], optional): A function to preprocess
                objects before storage. Defaults to None.
            batch_size (Optional[int], optional): Number of objects to write in
                a single Redis pipeline execution. Defaults to class's
                default batch size.

        Returns:
            List[str]: List of keys loaded to Redis.

        Raises:
            SchemaValidationError: If validation fails when validate_on_load is enabled.
            RedisVLError: If there's an error loading data to Redis.
        objectsrh  rR  r_  ri  rM  validate,Data validation failed during load operationN!Error while loading data to RedisFailed to load data: )r   writer   r   r1   r   errorr"  r#  r0   rY   )r   rg  rh  rR  r_  ri  rM  r%  s           rd   loadzSearchIndex.loadP  s    L	H=&&"!%%/ ' 	 	 	 % 	 	 	LLGHHH 	H 	H 	H@AAA?s1vv??@@aG	Hs    +. 
BAB :BBrT   c                     | j                             | j        |                     |          g          }|rt	          |d                   S dS )a  Fetch an object from Redis by id.

        The id is typically either a unique identifier,
        or derived from some domain-specific metadata combination
        (like a document id or chunk id).

        Args:
            id (str): The specified unique identifier for a particular
                document indexed in Redis.

        Returns:
            Dict[str, Any]: The fetched object.
        r   N)r   rW   r   r   r   )r   rT   objs      rd   fetchzSearchIndex.fetch  sI     m 2TXXb\\NCC 	) Q(((trf   aggregation_queryc                 |    |                      ||j                  }t          ||| j        j        j                  S )7Execute an aggregation query and processes the results.query_paramsrM   rm   	aggregateparamsr   rN   rl   rm   r   rw  rL   s      rd   
_aggregatezSearchIndex._aggregate  sM    ..*1 ! 
 
 )#*7
 
 
 	
rf   	sql_queryc                 &   	 ddl m} ddlm} n# t          $ r t	          d          w xY w || j                  }|                                  || j        |          }|                    |j        |j	                  }d |j
        D             S )a*  Execute a SQL query and return results.

        Args:
            sql_query: The SQLQuery object containing the SQL statement.

        Returns:
            List of dictionaries containing the query results.

        Raises:
            ImportError: If sql-redis package is not installed.
        r   )Executor)SchemaRegistry\sql-redis is required for SQL query support. Install it with: pip install redisvl[sql-redis]r  c                 ,    g | ]}t          |          S rh   r   ri   r   s     rd   rj   z*SearchIndex._sql_query.<locals>.<listcomp>       :::sc"":::rf   )sql_redis.executorr  sql_redis.schemar  r   r   load_allrd  sqlr  r   )r   r  r  r  registryexecutorr   s          rd   
_sql_queryzSearchIndex._sql_query  s    	3333337777777 	 	 	B  	 ">$"4558D.99 !!)-	8H!II::fk::::s    )r$   c                 ~   	  | j                             | j        j        j                  j        |i |S # t          j        j        $ rE}dt          |          v rt          d          t          dt          |                     |d}~wt          $ r%}t          dt          |                     |d}~ww xY w)7  Perform an aggregation operation against the index.

        Wrapper around the aggregation API that adds the index name
        to the query and passes along the rest of the arguments
        to the redis-py ft().aggregate() method.

        Returns:
            Result: Raw Redis aggregation results.
        	CROSSSLOTNCross-slot error during aggregation. Ensure consistent hash tags in your keys.Error while aggregating: N$Unexpected error while aggregating: )r   r  rN   rl   rI   r~  r  r   r!  rY   r/   r"  r   r   r   r%  s       rd   r~  zSearchIndex.aggregate  s    	J4%(():)?@@J   * 	P 	P 	Pc!ff$$&d   ##Gs1vv#G#GHHaO 	 	 	"?s1vv?? 	s"   36 B<
A B

B< B77B<
   queriesr&   c                    g }| j                             | j        j        j                  }i }t          | j                   dvr
d|t          <   t          dt          |          |          D ]Q}||||z            }| j         	                    d          5 }g }	|D ]~}
t          |
t                    r'|                    |
d         |
d                   \  }}n|                    |
d          \  }}|	                    |            |j        d	g|R i | t          j                    }|                                }t          j                    |z
  d
z  }t#          |          D ]:\  }}|	|         }|                    |||          }|                    |           ;	 ddd           n# 1 swxY w Y   S|S )a  Perform a search against the index for multiple queries.

        This method takes a list of queries and optionally query params and
        returns a list of Result objects for each query. Results are
        returned in the same order as the queries.

        NOTE: Cluster users may need to incorporate hash tags into their query
        to avoid cross-slot operations.

        Args:
            queries (List[SearchParams]): The queries to search for.
            batch_size (int, optional): The number of queries to search for at a time.
                Defaults to 10.

        Returns:
            List[Result]: The search results for each query.
        3r   Tr   Ftransaction   rz  N	FT.SEARCH     @@rM   duration)r   r  rN   rl   rI   r*   r)   ranger   rb  rX   tuple_mk_query_argsr-  r/  timerd  	enumerate_parse_search)r   r  rM  all_resultsrH   optionsibatch_queriesre  batch_built_queriesrM   
query_argsqstrL   r  jquery_results_built_queryparsed_results                       rd   batch_searchzSearchIndex.batch_search  sZ   ( #&&t{'8'=>> 2338CC$(GL!q#g,,
33 '	6 '	6A#AJ$67M
 #,,,?? !64&(#*  E!%// (.(=(=!!H58 )> ) )
AA )/(=(=! )> ) )
A (..q111(D(##   "    Y[[,,.. !IKK",6(1'(:(: 6 6$A}#6q#9L$*$8$8%*!) %9 % %M  &&}555563!6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6D s   DF22F6	9F6	c                     	 t          | j        t                    r7t          | j                            | j        j        j                  g|R i |S  | j                            | j        j        j                  j        |i |S # t          j
        j        $ rE}dt          |          v rt          d          t          dt          |                     |d}~wt          $ r%}t          dt          |                     |d}~ww xY w)a  Perform a search against the index.

        Wrapper around the search API that adds the index name
        to the query and passes along the rest of the arguments
        to the redis-py ft().search() method.

        Returns:
            Result: Raw Redis search results.
        r  ICross-slot error during search. Ensure consistent hash tags in your keys.Error while searching: N"Unexpected error while searching: )rX   r   r   r   r  rN   rl   rI   rH   r  r   r!  rY   r/   r"  r  s       rd   rH   zSearchIndex.search%  sP   	Y$,l;; 
%&))$+*;*@AA      Lt),,T[->-CDDK#   * 	N 	N 	Nc!ff$$&_   ##ESVV#E#EFFAM 	Y 	Y 	Y"#PA#P#PQQWXX	Ys+   AB 3B DA CD( DDrM   c                 j   | j                             | j        j        j                  }|                     |           t          |d          st          t                     |j	        d|j
        |j        |j                                        r|j        nd|j        d|}d |j        D             S )a  Perform a hybrid search against the index, combining text and vector search.

        Args:
            query (HybridQuery): The text+vector search query to be performed, with configurable fusion methods and
                post-processing.
            kwargs: Additional arguments to pass to the redis-py hybrid_search method (e.g. timeout).

        Returns:
            List[Dict[str, Any]]: The search results ordered by combined score unless otherwise specified.

        Notes:
            Hybrid search is only available in Redis 8.4.0+, and requires redis-py >= 7.1.0.

        See Also:
            - `FT.HYBRID command documentation <https://redis.io/docs/latest/commands/ft.hybrid>`_
            - `redis-py hybrid_search documentation <https://redis.readthedocs.io/en/stable/redismodules.html#redis.commands.search.commands.SearchCommands.hybrid_search>`_

        .. code-block:: python

            from redisvl.query import HybridQuery

            hybrid_query = HybridQuery(
                text="lorem ipsum dolor sit amet",
                text_field_name="description",
                vector=[0.1, 0.2, 0.3],
                vector_field_name="embedding"
            )

            results = index.query(hybrid_query)

        hybrid_searchNrM   combine_methodpost_processingparams_substitutionc                 ,    g | ]}t          |          S rh   r  ri   r   s     rd   rj   z.SearchIndex._hybrid_search.<locals>.<listcomp>u       :::Qa  :::rf   rh   )r   r  rN   rl   rI   r   hasattrr   r   r  rM   combination_methodpostprocessing_config
build_argsr  rL   )r   rM   r   rl   rL   s        rd   _hybrid_searchzSearchIndex._hybrid_searchD  s    @ "%%dk&7&<==##E***uo.. 	<:;;;%%% 

+ 3 .99;;++ %

 

 

 

 ;:'/::::rf   c                     |                      d |D             |          }g }t          ||          D ]1\  }}t          ||| j                  }|                    |           2|S )z/Execute a batch of queries and process results.c                 *    g | ]}|j         |j        fS rh   rM   r  ri   rM   s     rd   rj   z+SearchIndex.batch_query.<locals>.<listcomp>|  !    >>>Uek5<(>>>rf   rM  rM   rN   r  zipr|   rN   r-  r   r  rM  rL   
all_parsedrM   batch_resultsparseds           rd   batch_queryzSearchIndex.batch_queryw  s     ##>>g>>>: $ 
 
 
$'$9$9 	& 	& E=$]%TTTF f%%%%rf   c                    	 |                      |           n2# t          $ r%}t          dt          |                     |d}~ww xY w|                     |j        |j                  }t          ||| j                  S )z$Execute a query and process results.Invalid query: Nrz  r  r   r-   rY   rH   rM   r  r|   rN   r   rM   r%  rL   s       rd   rK  zSearchIndex._query  s    	J  ''''# 	J 	J 	J&'AQ'A'ABBI	J++ek+EEweDKHHHHs    
A AAc                 (   t          |t                    r|                     |          S t          |t                    r|                     |          S t          |t
                    r|                     |          S |                     |          S )a  Execute a query on the index.

        This method takes a BaseQuery, AggregationQuery, or HybridQuery object directly, and
        handles post-processing of the search.

        Args:
            query (Union[BaseQuery, AggregationQuery, HybridQuery]): The query to run.

        Returns:
            List[Result]: A list of search results.

        .. code-block:: python

            from redisvl.query import VectorQuery

            query = VectorQuery(
                vector=[0.16, -0.34, 0.98, 0.23],
                vector_field_name="embedding",
                num_results=3
            )

            results = index.query(query)

        rX   r5   r  r   r  r   r  rK  r   rM   s     rd   rM   zSearchIndex.query  s    6 e-.. 	&??5)))x(( 	&??5))){++ 	&&&u---;;u%%%rf      	page_sizec              #      K   t          |t                    st          d          |dk    rt          d          d}	 |                    ||           |                     |          }|sdS |V  ||z  }9)a  Execute a given query against the index and return results in
        paginated batches.

        This method accepts a RedisVL query instance, enabling pagination of
        results which allows for subsequent processing over each batch with a
        generator.

        Args:
            query (BaseQuery): The search query to be executed.
            page_size (int, optional): The number of results to return in each
                batch. Defaults to 30.

        Yields:
            A generator yielding batches of search results.

        Raises:
            TypeError: If the page_size argument is not of type int.
            ValueError: If the page_size argument is less than or equal to zero.

        .. code-block:: python

            # Iterate over paginated search results in batches of 10
            for result_batch in index.paginate(query, page_size=10):
                # Process each batch of results
                pass

        Note:
            The page_size parameter controls the number of items each result
            batch contains. Adjust this value based on performance
            considerations and the expected volume of search results.

        Note:
            For stable pagination, the query must have a `sort_by` clause.

        zpage_size must be an integerr    page_size must be greater than 0TNrX   r6  r   r\   rJ  rK  )r   rM   r  offsetrL   s        rd   paginatezSearchIndex.paginate  s      H )S)) 	<:;;;>>?@@@	 LL+++kk%((G MMMiF	 rf   c                 P    t          | j                            d                    S )List all search indices in Redis database.

        Returns:
            List[str]: The list of indices in the database.
        FT._LIST)r   r   r/  r   s    rd   listallzSearchIndex.listall  s#     T/??
KKLLLrf   c                 L    | j         j        j        |                                 v S ){Check if the index exists in Redis.

        Returns:
            bool: True if the index exists, False otherwise.
        rN   rl   rI   r  r   s    rd   r  zSearchIndex.exists  s     { %77rf   c           	      |   	 t          |t                    r<|                                }|                    d| |          }t	          |          }n'|                    |                                           }t          |          S # t          $ r(}t          d|  dt          |                     |d}~ww xY w)z1Run FT.INFO to fetch information about the index.FT.INFOr*  Error while fetching  index info: N)rX   r    get_random_noder/  r   r  r   r   r"  r/   rY   rI   r   noder   r   r%  s         rd   r   zSearchIndex._info  s    	,(899 4#3355%55t$ 6   !((#t,,1133 &&& 	 	 	"CCC3q66CC 	s   BB	 	
B;#B66B;c                 ^    |p| j         j        j        }|                     || j                  S )Get information about the index.

        Args:
            name (str, optional): Index name to fetch info about.
                Defaults to None.

        Returns:
            dict: A dictionary containing the information about the index.
        )rN   rl   rI   r   r   )r   rI   r  s      rd   r   zSearchIndex.info
  s-     3T[.3
zz*d&8999rf   c                     | S r   rh   r   s    rd   	__enter__zSearchIndex.__enter__  s    rf   c                 .    |                                   d S r   r   r   exc_typeexc_valexc_tbs       rd   __exit__zSearchIndex.__exit__  s    rf   )NNNFNNr   rO   NFFT)NNNNNrO   r$   r  rO   r&   r  )=r   r   r   r   r!   rA   r   r   rY   r   r   r   r   r   r   r   r   r   r   r"   r   r  r  r&  r  r   r6  r<  r,  r   rU  r^  rf  r
   r   rs  rv  r5   r  r   r  r~  SearchParamsr  rH   r   r  r   r'   r  rK  rM   r	   r  r  r  staticmethodr   r   r  r   rh   rf   rd   r   r     s        8 *,LMM 37#'6:!&+4 +4+4 /+4 C=	+4
 $DcN3+4 +4 +4 +4 NM+4Z# # #  37#'	&3 &3&3 /&3 C=	&3 &3 &3 [&3P #1 # # # X# # # # # X#4 $MNN
 
# 
 
 
 ON
, 'PQQ    RQ$P P P PJ J JD JT J J J JXS S4 S S S SB(S	 (c ( ( ( (4%s % % % %@3eCcN3 3 3 3 3 32%T#Y"7 2C 2 2 2 2@8#tCy.)8038	sDI~	8 8 8 8( #'(,!)-$(8H 8Hsm8H 3-8H x}%	8H
 c]8H X&8H SM8H 
c8H 8H 8H 8Ht c3h 8    &

,< 

d3PS8nAU 

 

 

 

;H ;d38n1E ; ; ; ;>   4 >@B BL)B7:B	hB B B BHY Y Y Y>1;K 1;d4S>>R 1; 1; 1; 1;h ?A 	*8;	d4S>"	#    II I$tCH~*> I I I I"&9&6XMN"&	d38n	"& "& "& "&H2  2 i 2 C 2  2  2  2  2 hMc M M M M8 8 8 8 8 C  4S>    \": :# :$sCx. : : : :      rf   r   c                      e Zd ZdZ edd          ddddddedee         d	ee         d
ee	ee
f                  def
d            Ze	 	 dKded	ee         dee         fd            Zedee         fd            Z edd          dLdee         fd            Z edd          d	eeef         fd            ZdefdZd	eeef         defdZeded	ede	ee
f         fd            ZdMdZdNdededdfdZdOdefdZdee         defd Zdefd!Z d"eeee         f         defd#Z!d$eeee         f         defd%Z"d"eeee         f         d&edeeee         f         fd'Z# ed(d)          	 	 	 	 	 	 dPd*e$e
         d+ee         d"ee$e                  d&ee         d,ee%         d(ee         d-ee         dee         fd.            Z&d/edee	ee
f                  fd0Z'd1e(dee	ee
f                  fd2Z)dQd4Z*	 dRd6ee+         d-eded7         fd8Z,dSd9Z-d:e.dee	ee
f                  fd;Z/	 dRd6ee0         d-edeee	ee
f                           fd<Z1d:e0dee	ee
f                  fd=Z2d>e3dee	ee
f                  fd?Z4d:ee0e(e.e3f         dee	ee
f                  fd@Z5dTd:e0dBede6fdCZ7dee         fdDZ8defdEZ9dLdee         de	ee
f         fdFZ:dG Z;dH Z<dI Z=dJ Z>dS )UAsyncSearchIndexaF  A search index class for interacting with Redis as a vector database in
    async-mode.

    The AsyncSearchIndex is instantiated with a reference to a Redis database
    and an IndexSchema (YAML path or dictionary object) that describes the
    various settings and field configurations.

    .. code-block:: python

        from redisvl.index import AsyncSearchIndex

        # initialize the index object with schema from file
        index = AsyncSearchIndex.from_yaml(
            "schemas/schema.yaml",
            redis_url="redis://localhost:6379",
            validate_on_load=True
        )

        # create the index
        await index.create(overwrite=True, drop=False)

        # data is an iterable of dictionaries
        await index.load(data)

        # delete index and data
        await index.delete(drop=True)

    redis_kwargsr   NF)r   r   r   r   rN   r   r   r   r   c                   d|v r|                     d          }t          |t                    st          d          || _        || _        |                     dd          | _        || _        || _        |pi | _	        t          j                    | _        |                     dd          | _        |du | _        | j        r)t          j        | t#          | j                             dS dS )aB  Initialize the RedisVL async search index with a schema.

        Args:
            schema (IndexSchema): Index schema object.
            redis_url (Optional[str], optional): The URL of the Redis server to
                connect to.
            redis_client (Optional[AsyncRedis]): An
                instantiated redis client.
            connection_kwargs (Optional[Dict[str, Any]]): Redis client connection
                args.
            validate_on_load (bool, optional): Whether to validate data against schema
                when loading. Defaults to False.
        r  r   r   Nr   F)r_   rX   rA   r\   rN   r   r   r   r   r   asyncior   r   r   r   r   r   r#   r   )r   rN   r   r   r   r   r   s          rd   r   zAsyncSearchIndex.__init__<  s    0 V## &

> : : &+.. 	HFGGG!1(.

:t(D(D *#"3"9r\^^
!',?!G!G".$"6" 	BT<#@#@AAAAA	B 	Brf   rI   c                 \  K   |s|st          d          |rt          j        dd|i| d{V }n!|rt          j        |           d{V  d|d<   |t          d          |                     ||           d{V }t          |          }t          j        |          } | |fd|i|S )	aW  
        Initialize from an existing search index in Redis by index name.

        Args:
            name (str): Name of the search index in Redis.
            redis_client(Optional[Redis]): An
                instantiated redis client.
            redis_url (Optional[str]): The URL of the Redis server to
                connect to.
        zJMust provide either a redis_url or redis_client to fetch Redis index info.r   NTr   zXFailed to obtain a valid Redis client. Please provide a valid redis_client or redis_url.r   rh   )r\   r<   _get_aredis_connectionvalidate_async_redisr   r=   rA   r   r   s           rd   r   zAsyncSearchIndex.from_existingj  s4     $  	 	\    		/!7!N " "#"" "      LL  	/(=lKKKKKKKKK*.F&'D   99T<88888888
2:>>&{33s6??????rf   rO   c                     | j         S r   )r   r   s    rd   r   zAsyncSearchIndex.client  s     !!rf   r   r   c                    K   t          j        dt                     t          j        dd|i| d{V }|                     |           d{V  dS )zP[DEPRECATED] Connect to a Redis instance. Use connection parameters in __init__.z?connect() is deprecated; pass connection parameters in __init__r   Nrh   )rw   rx   DeprecationWarningr<   r  r  )r   r   r   r   s       rd   r   zAsyncSearchIndex.connect  s       	M	
 	
 	
 .D 
 

#)
 
 
 
 
 
 
 
 oof%%%%%%%%%%%rf   r  c                    K   |                      |           d{V }|                                  d{V  | j        4 d{V  || _        ddd          d{V  n# 1 d{V swxY w Y   | S )z
        [DEPRECATED] Manually set the Redis client to use with the search index.
        This method is deprecated; please provide connection parameters in __init__.
        N)_validate_clientr   r   r   )r   r   s     rd   r  zAsyncSearchIndex.set_client  s      "22<@@@@@@@@oo: 	. 	. 	. 	. 	. 	. 	. 	.!-D	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	.s   A
A),A)c                   K   | j         | j        4 d{V  | j         Gi | j        }| j        r
| j        |d<   | j        r
| j        |d<   t          j        di | d{V | _         	 ddd          d{V  n# 1 d{V swxY w Y   | j        s3| j        r,t          j        | j         | j                   d{V  d| _        | j         S )z5Lazily instantiate and return the async Redis client.Nr   r   Trh   )	r   r   r   r   r   r<   r  r   r  r   s     rd   _get_clientzAsyncSearchIndex._get_client  s     %z        %-8 78F >.2o{+~ <-1^z*4KUUfUUUUUUUU &                            % 	*$. 	*(="         &*D"!!s   AA99
BBc                    K   t          |t          t          f          r0t          j        dt
                     t          j        |          }|S t          |t          t          f          st          d          |S )NzPassing a sync Redis client to AsyncSearchIndex is deprecated and will be removed in the next major version. Please use an async Redis client instead.zBInvalid async client type: must be AsyncRedis or AsyncRedisCluster)rX   r   r   rw   rx   r  r<   sync_to_async_redis
AsyncRedisAsyncRedisClusterr\   )r   r   async_redis_clients      rd   r  z!AsyncSearchIndex._validate_client  s       lUL$9:: 	M. #	   ':<HH  &%L:7H*IJJ 	T   rf   c           	        K   	 t          |t                    rB|                                }|                    d| |           d {V }t	          |          }n-|                    |                                            d {V }t          |          S # t          $ r(}t          d|  dt          |                     |d }~ww xY w)Nr  r  r  r  )rX   r  r  r/  r   r  r   r   r"  r/   rY   r  s         rd   r   zAsyncSearchIndex._info  s	     	,(9:: :#3355+;;t$  <           !(()__T227799999999 &&& 	 	 	"CCC3q66CC 	s   BB 
C	!#CC	c                    K   |                                   d{V }t          |           d{V st          j        t                    dS r  )r  r?   r.   r  r@   )r   r   s     rd   _check_svs_support_asyncz)AsyncSearchIndex._check_svs_support_async  sl       ''))))))))'//////// 	P)89NOOO	P 	Prf   r  r	  c           	        K   |                                   d{V }| j        j        }|st          d          t	          |t
                    st          d          |                                 r|                                  d{V  | 	                                 d{V rS|st                              d           dS t                              d           |                     |           d{V  	 | j        j        j        }t	          |t                    r|n|g}t!          || j        j                  }| j        j        j        }t	          |t(                    r+t+          | j        j        j        ||||           d{V  dS |                    | j        j        j                                      |||           d{V  dS # t2          j        j        $ r-}	t9          d	| j         d
t;          |	                     |	d}	~	wt<          $ rG}	t                              d           t9          d| j         dt;          |	                     |	d}	~	ww xY w)a  Asynchronously create an index in Redis with the current schema
            and properties.

        Args:
            overwrite (bool, optional): Whether to overwrite the index if it
                already exists. Defaults to False.
            drop (bool, optional): Whether to drop all keys associated with the
                index in the case of overwriting. Defaults to False.

        Raises:
            RuntimeError: If the index already exists and 'overwrite' is False.
            ValueError: If no fields are defined for the index.

        .. code-block:: python

            # create an index in Redis; only if one does not exist with given name
            await index.create()

            # overwrite an index in Redis without dropping associated data
            await index.create(overwrite=True)

            # overwrite an index in Redis; drop associated data (clean slate)
            await index.create(overwrite=True, drop=True)
        Nr  r  r  r  r  r  r  r  r  r  r  r  ) r  rN   r  r\   rX   r   r   r   r!  r  r   r   r  rl   r   r   r,   r   r   r   r  r   rI   r  r  r  r   r!  r/   rY   r"  r#  )
r   r  r	  r   r  r   r$  r  r   r%  s
             rd   r&  zAsyncSearchIndex.create   s     2 '')))))))){/ 	<:;;;)T** 	><===   "" 	2//111111111 	$ DEEEtKK<===++d######### 	[&-F$.vt$<$<J&&6(K("t}/A  J )3I&"344 0#{05!')'            ii 1 677DD')' E           
 * 	 	 	"J49JJ#a&&JJ   	 	 	EFFF"JDIJJ#a&&JJ 	s-   :BG A G I#'(HI#AII#Tc                    K   |                                   d{V }	 |rCt          |t                    r.|                                  d{V  d| j        j        j        g}n*d| j        j        j        g}|r|                    d           t          |t                    r*|                                g} |j	        |d|i d{V  dS  |j	        |  d{V  dS # t          $ r%}t          dt          |                     |d}~ww xY w)zDelete the search index.

        Args:
            drop (bool, optional): Delete the documents in the index.
                Defaults to True.

        Raises:
            redis.exceptions.ResponseError: If the index does not exist.
        Nr(  r)  r*  r+  )r  rX   r  r,  rN   rl   rI   r-  r.  r/  r"  r/   rY   )r   r	  r   r0  r*  r%  s         rd   r  zAsyncSearchIndex.deleteN  sq      ''))))))))	S  	*
6+<== 	*jjll"""""""*DK,=,BC +DK,=,BC *OOD)))&"344 8 & 7 7 9 9:,f,hR\RRRRRRRRRRR,f,h7777777777 	S 	S 	S"#J#a&&#J#JKKQRR	Ss   B,C C 
D( DDr1  c                   K   |                                   d{V }t          |t                    }|r{d}|D ]u}	 |t          t          |                    |           d{V           z  }5# t          j        j        $ r*}t          
                    d| d|            Y d}~nd}~ww xY wn |j        |  d{V }|S )r3  Nr   r4  r5  )r  rX   r  r   r6  r  r  r   r!  r   r7  r8  s          rd   r<  zAsyncSearchIndex._delete_batcho  s*      ''))))))))(9::
 
	H'($!+ Q QQ,6==#?#???????1 1 ,, '2 Q Q QNN#O=#O#OA#O#OPPPPPPPPQQ .;V]J-G'G'G'G'G'G'G$''s   1A--B+ B&&B+c                   K   d}d}|                                   d{V }t          |d         |z            }d}t          t          d          dg          }|                    d|           	 |                     |           d{V }|r1||k    r+d
 |D             }||                     |           d{V z  }nnP|S )a  Clear all keys in Redis associated with the index, leaving the index
        available and in-place for future insertions or updates.

        NOTE: This method requires custom behavior for Redis Cluster because here,
        we can't easily give control of the keys we're clearing to the user so they
        can separate them based on hash tag.

        Returns:
            int: Count of records deleted from Redis.
        r>  r?  Nr@  r   rA  rT   rB  Tc                     g | ]
}|d          S rE  rh   rF  s     rd   rj   z*AsyncSearchIndex.clear.<locals>.<listcomp>  rH  rf   rI  rL  s	            rd   r,  zAsyncSearchIndex.clear  s      
	YY[[      "y(
 
 &',S11$HHHQ
###	++e,,,,,,,,E .2EEE?????
%t/A/A*/M/M)M)M)M)M)M)MM%%	 %$rf   rR  c                    K   |                                   d{V }t          |t                    r |j        |  d{V S |                    |           d{V S )rT  N)r  rX   r   r  )r   rR  r   s      rd   rU  zAsyncSearchIndex.drop_keys  s       ''))))))))dD!! 	-&--------t,,,,,,,,,rf   rV  c                 p   K                                      d{V }t          |t                    rU|sdS  fd|D             }t          |t                    rt	          |          st          d           |j        |  d{V S                      |          }|                    |           d{V S )rX  Nr   c                 :    g | ]}                     |          S rh   rZ  r[  s     rd   rj   z3AsyncSearchIndex.drop_documents.<locals>.<listcomp>  r\  rf   r]  )r  rX   r   r  r   r\   r  r   )r   rV  r   rR  r   s   `    rd   r^  zAsyncSearchIndex.drop_documents  s        ''))))))))c4   	, q////3///D&"344 =QRV=W=W  N   '--------((3--Cs+++++++++rf   r_  c                 .  K   |                                   d{V }t          |t                    rI|                                }|D ]}|                    ||           |                                 d{V S |                    ||           d{V S )ra  N)r  rX   r   rb  rc  rd  )r   rR  r_  r   re  r   s         rd   rf  zAsyncSearchIndex.expire_keys  s       ''))))))))dD!! 	2??$$D & &C%%%%'''''''tS111111111rf   concurrencyzUse batch_size instead.rg  rh  ri  rM  c           
      ~  K   |                                   d{V }	 | j                            |||||||| j                   d{V S # t          $ r }	t
                              d            d}	~	wt          $ r?}	t
                              d           t          dt          |	                     |	d}	~	ww xY w)a  Asynchronously load objects to Redis. Returns the list of keys loaded
        to Redis.

        RedisVL automatically handles constructing the object keys, batching,
        optional preprocessing steps, and setting optional expiration
        (TTL policies) on keys.

        Args:
            data (Iterable[Any]): An iterable of objects to store.
            id_field (Optional[str], optional): Specified field used as the id
                portion of the redis key (after the prefix) for each
                object. Defaults to None.
            keys (Optional[Iterable[str]], optional): Optional iterable of keys.
                Must match the length of objects if provided. Defaults to None.
            ttl (Optional[int], optional): Time-to-live in seconds for each key.
                Defaults to None.
            preprocess (Optional[Callable], optional): A function to
                preprocess objects before storage. Defaults to None.
            batch_size (Optional[int], optional): Number of objects to write in
                a single Redis pipeline execution. Defaults to class's
                default batch size.

        Returns:
            List[str]: List of keys loaded to Redis.

        Raises:
            SchemaValidationError: If validation fails when validate_on_load is enabled.
            RedisVLError: If there's an error loading data to Redis.

        .. code-block:: python

            data = [{"test": "foo"}, {"test": "bar"}]

            # simple case
            keys = await index.load(data)

            # set 360 second ttl policy on data
            keys = await index.load(data, ttl=360)

            # load data with predefined keys
            keys = await index.load(data, keys=["rvl:foo", "rvl:bar"])

            # load data with preprocessing step
            def add_field(d):
                d["new_field"] = 123
                return d
            keys = await index.load(data, preprocess=add_field)

        Nrk  rn  ro  rp  )r  r   awriter   r1   r   rr  r"  r#  r0   rY   )
r   rg  rh  rR  r_  ri  r+  rM  r   r%  s
             rd   rs  zAsyncSearchIndex.load  s     x ''))))))))	H--!%%/ . 	 	 	 	 	 	 	 	 	 % 	 	 	LLGHHH 	H 	H 	H@AAA?s1vv??@@aG	Hs#   ,A 
B<A00B<=:B77B<rT   c                    K   |                                   d{V }| j                            ||                     |          g           d{V }|rt	          |d                   S dS )a  Asynchronously etch an object from Redis by id. The id is typically
        either a unique identifier, or derived from some domain-specific
        metadata combination (like a document id or chunk id).

        Args:
            id (str): The specified unique identifier for a particular
                document indexed in Redis.

        Returns:
            Dict[str, Any]: The fetched object.
        Nr   )r  r   agetr   r   )r   rT   r   ru  s       rd   rv  zAsyncSearchIndex.fetch<  s       ''))))))))M&&v~>>>>>>>> 	) Q(((trf   rw  c                    K   |                      ||j                   d{V }t          ||| j        j        j                  S )ry  rz  Nr|  r}  r  s      rd   r  zAsyncSearchIndex._aggregateN  sq       *1 ' 
 
 
 
 
 
 
 
 )#*7
 
 
 	
rf   r$   c                   K   |                                   d{V }	  |                    | j        j        j                  j        |i | d{V S # t          j        j        $ rE}dt          |          v rt          d          t          dt          |                     |d}~wt          $ r%}t          dt          |                     |d}~ww xY w)r  Nr  r  r  r  )r  r  rN   rl   rI   r~  r  r   r!  rY   r/   r"  r   r   r   r   r%  s        rd   r~  zAsyncSearchIndex.aggregate\  s      ''))))))))	D4;#4#9::DdUfUUUUUUUUU* 	P 	P 	Pc!ff$$&d   ##Gs1vv#G#GHHaO 	 	 	"?s1vv?? 	s$   4A C'A B''C4 CCr  r  r&   c                   K   g }|                                   d{V }|                    | j        j        j                  }i }t          |          dvr
d|t          <   t          dt          |          |          D ]d}||||z            }|	                    d          4 d{V }	g }
|D ]~}t          |t                    r'|                    |d         |d                   \  }}n|                    |d          \  }}|
                    |            |	j        d	g|R i | t          j                    }|	                                 d{V }t          j                    |z
  d
z  }t#          |          D ]:\  }}|
|         }|                    |||          }|                    |           ;	 ddd          d{V  n# 1 d{V swxY w Y   f|S )a  Asynchronously execute a batch of search queries.

        This method takes a list of search queries and executes them in batches
        to improve performance when dealing with multiple queries.

        NOTE: Cluster users may need to incorporate hash tags into their query
        to avoid cross-slot operations.

        Args:
            queries (List[SearchParams]): A list of search queries to execute.
                Each query can be either a string or a tuple of (query, params).
            batch_size (int, optional): The number of queries to execute in each
                batch. Defaults to 10.

        Returns:
            List[Result]: A list of search results corresponding to each query.

        .. code-block:: python

            queries = [
                "hello world",
                ("goodbye world", {"num_results": 5}),
            ]

            results = await index.batch_search(queries)
        Nr  Tr   Fr  r  rz  r  r  r  )r  r  rN   rl   rI   r*   r)   r  r   rb  rX   r  r  r-  r/  r  rd  r  r  )r   r  rM  r  r   rH   r  r  r  re  r  rM   r  r  r  rL   r  r  r  r  r  s                        rd   r  zAsyncSearchIndex.batch_searcht  s     : ''))))))))4;,122''x77$(GL!q#g,,
33 '	6 '	6A#AJ$67M
 599 !6 !6 !6 !6 !6 !6 !6T&(#*  E!%// (.(=(=!!H58 )> ) )
AA )/(=(=! )> ) )
A (..q111(D(##   "    Y[[ $...... !IKK",6(1'(:(: 6 6$A}#6q#9L$*$8$8%*!) %9 % %M  &&}555563!6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6 !6D s   *DG
G	G	c                 R  K   	 |                                   d{V }t          |t                    r8t          |                    | j        j        j                  g|R i | d{V S  |                    | j        j        j                  j        |i | d{V S # t          j
        j        $ rE}dt          |          v rt          d          t          dt          |                     |d}~wt          $ r%}t          dt          |                     |d}~ww xY w)a!  Perform an async search against the index.

        Wrapper around the search API that adds the index name
        to the query and passes along the rest of the arguments
        to the redis-py ft().search() method.

        Returns:
            Result: Raw Redis search results.
        Nr  r  r  r  )r  rX   r  r   r  rN   rl   rI   rH   r  r   r!  rY   r/   r"  r2  s        rd   rH   zAsyncSearchIndex.search  s     	Y++--------F&"344 W1IIdk/455            FVYYt{'8'=>>EtVvVVVVVVVVV* 	N 	N 	Nc!ff$$&_   ##ESVV#E#EFFAM 	Y 	Y 	Y"#PA#P#PQQWXX	Ys+   A&B  +4B   D&4A C44D& D!!D&rM   c                   K   |                                   d{V }|                    | j        j        j                  }|                     |           t          |d          st          t                     |j	        d|j
        |j        |j                                        r|j        nd|j        d| d{V }d |j        D             S )a  Perform a hybrid search against the index, combining text and vector search.

        Args:
            query (HybridQuery): The text+vector search query to be performed, with configurable fusion methods and
                post-processing.
            kwargs: Additional arguments to pass to the redis-py hybrid_search method (e.g. timeout).

        Returns:
            List[Dict[str, Any]]: The search results ordered by combined score unless otherwise specified.

        Notes:
            Hybrid search is only available in Redis 8.4.0+, and requires redis-py >= 7.1.0.

        .. code-block:: python

            from redisvl.query import HybridQuery

            hybrid_query = HybridQuery(
                text="lorem ipsum dolor sit amet",
                text_field_name="description",
                vector=[0.1, 0.2, 0.3],
                vector_field_name="embedding"
            )

            results = await async_index.query(hybrid_query)

        Nr  r  c                 ,    g | ]}t          |          S rh   r  r  s     rd   rj   z3AsyncSearchIndex._hybrid_search.<locals>.<listcomp>  r  rf   rh   )r  r  rN   rl   rI   r   r  r   r   r  rM   r  r  r  r  rL   )r   rM   r   r   rl   rL   s         rd   r  zAsyncSearchIndex._hybrid_search  s     < ''))))))))		$++011##E***uo.. 	<:;;;++ 

+ 3 .99;;++ %

 

 

 

 

 

 

 

 

 

 ;:'/::::rf   c                    K   |                      d |D             |           d{V }g }t          ||          D ]1\  }}t          ||| j                  }|                    |           2|S )z>Asynchronously execute a batch of queries and process results.c                 *    g | ]}|j         |j        fS rh   r  r  s     rd   rj   z0AsyncSearchIndex.batch_query.<locals>.<listcomp>  r  rf   r  Nr  r  r  s           rd   r  zAsyncSearchIndex.batch_query  s       ))>>g>>>: * 
 
 
 
 
 
 
 
 
$'$9$9 		& 		& E=${  F f%%%%rf   c                   K   	 |                      |           n2# t          $ r%}t          dt          |                     |d}~ww xY w|                     |j        |j                   d{V }t          ||| j                  S )z3Asynchronously execute a query and process results.r  Nrz  r  r  r  s       rd   rK  zAsyncSearchIndex._query'  s      	J  ''''# 	J 	J 	J&'AQ'A'ABBI	JEKelKKKKKKKKweDKHHHHs    
A	 AA	r  c                 Z  K   	 ddl m}m} n# t          $ r t          d          w xY w|                                  d{V } ||          }|                                 d{V   |||          }|                    |j        |j                   d{V }d |j	        D             S )a9  Asynchronously execute a SQL query and return results.

        Args:
            sql_query: The SQLQuery object containing the SQL statement.

        Returns:
            List of dictionaries containing the query results.

        Raises:
            ImportError: If sql-redis package is not installed.
        r   )AsyncExecutorAsyncSchemaRegistryr  Nr  c                 ,    g | ]}t          |          S rh   r  r  s     rd   rj   z/AsyncSearchIndex._sql_query.<locals>.<listcomp>M  r  rf   )
	sql_redisr;  r<  r   r  r  rd  r  r  r   )r   r  r;  r<  r   r  r  r   s           rd   r  zAsyncSearchIndex._sql_query0  s
     	DDDDDDDDD 	 	 	B  	 ''))))))))&&v..!!!!!!!!! =22  ''	i>N'OOOOOOOO::fk::::s    'c                 \  K   t          |t                    r|                     |           d{V S t          |t                    r|                     |           d{V S t          |t
                    r|                     |           d{V S |                     |           d{V S )a  Asynchronously execute a query on the index.

        This method takes a BaseQuery, AggregationQuery, HybridQuery, or SQLQuery object
        directly, runs the search, and handles post-processing of the search.

        Args:
            query (Union[BaseQuery, AggregationQuery, HybridQuery, SQLQuery]): The query to run.

        Returns:
            List[Result]: A list of search results.

        .. code-block:: python

            from redisvl.query import VectorQuery

            query = VectorQuery(
                vector=[0.16, -0.34, 0.98, 0.23],
                vector_field_name="embedding",
                num_results=3
            )

            results = await index.query(query)
        Nr  r  s     rd   rM   zAsyncSearchIndex.queryO  s      4 e-.. 	,/////////x(( 	,/////////{++ 	,,,U333333333U+++++++++rf   r  r  c                   K   t          |t                    st          d          |dk    rt          d          d}	 |                    ||           |                     |           d{V }|sdS |W V  ||z  }@)a  Execute a given query against the index and return results in
        paginated batches.

        This method accepts a RedisVL query instance, enabling async pagination
        of results which allows for subsequent processing over each batch with a
        generator.

        Args:
            query (BaseQuery): The search query to be executed.
            page_size (int, optional): The number of results to return in each
                batch. Defaults to 30.

        Yields:
            An async generator yielding batches of search results.

        Raises:
            TypeError: If the page_size argument is not of type int.
            ValueError: If the page_size argument is less than or equal to zero.

        .. code-block:: python

            # Iterate over paginated search results in batches of 10
            async for result_batch in index.paginate(query, page_size=10):
                # Process each batch of results
                pass

        Note:
            The page_size parameter controls the number of items each result
            batch contains. Adjust this value based on performance
            considerations and the expected volume of search results.

        Note:
            For stable pagination, the query must have a `sort_by` clause.

        zpage_size must be of type intr   r  TNr  )r   rM   r  firstrL   s        rd   r  zAsyncSearchIndex.paginater  s      H )S)) 	=;<<<>>?@@@	LL	*** KK........G MMMMYE	rf   c                 ,  K   |                                   d{V }t          |t                    r<|                                }t	          |                    d           d{V           S t	          |                    d           d{V           S )r  Nr  )r  rX   r  r  r   r/  )r   r   r*  s      rd   r  zAsyncSearchIndex.listall  s       ''))))))))f/00 	K!1133L |'C'CJ'O'O!O!O!O!O!O!OPPP v'='=j'I'I!I!I!I!I!I!IJJJrf   c                 \   K   | j         j        j        |                                  d{V v S )r  Nr  r   s    rd   r  zAsyncSearchIndex.exists  s5       { %t||~~)=)=)=)=)=)===rf   c                    K   |                                   d{V }|p| j        j        j        }|                     ||           d{V S )r  N)r  rN   rl   rI   r   )r   rI   r   r  s       rd   r   zAsyncSearchIndex.info  sc       ''))))))))3T[.3
ZZ
F333333333rf   c                 z   K   | j         du rd S | j        | j                                         d {V  d | _        d S NF)r   r   acloser   s    rd   r   zAsyncSearchIndex.disconnect  sW      "e++F)$++---------!rf   c                 b    | j         	| j        du rd S  t          | j                               d S rF  )r   r   r#   r   r   s    rd   disconnect_syncz AsyncSearchIndex.disconnect_sync  s;    %)@E)I)IF%T_%%'''''rf   c                 
   K   | S r   rh   r   s    rd   
__aenter__zAsyncSearchIndex.__aenter__  s      rf   c                 >   K   |                                   d {V  d S r   r  r  s       rd   	__aexit__zAsyncSearchIndex.__aexit__  s.      oorf   r  r   r  r  r  )NNNNNNr  r  r  r  )?r   r   r   r   r!   rA   r   rY   r   r   r   r   r   r   r   r   r   r"   r   r   r   r  r  r  r
  r   r!  r&  r  r   r6  r<  r,  rU  r^  rf  r
   r   rs  rv  r5   r  r~  r	  r  rH   r   r  r'   r  rK  r   r  rM   r   r  r  r  r   r   rI  rK  rM  rh   rf   rd   r  r    sV        : )IJJ
 $(376:!&+B +B +B+B C=	+B
 /0+B $DcN3+B +B +B +B KJ+BZ  48#'	+@ +@+@ /0+@ C=	+@ +@ +@ [+@Z "!12 " " " X" $MNN	& 	&x} 	& 	& 	& ON	& 'PQQ	U3C_3T-U 	 	 	 RQ	"#3 " " " "0!"2O"CD	   0 # -= $sCx.    \ P P P PL Ld L$ L4 L L L L\S S S S S SB(d3i (C ( ( ( (8%S % % % %@-E#tCy.$9 -c - - - -,c49n(= ,# , , , ,>2#tCy.)2032	sDI~	2 2 2 2$ (ABB #'(,!)-%)$(NH NHsmNH 3-NH x}%	NH
 c]NH X&NH c]NH SMNH 
cNH NH NH CBNH`c htCH~&>    $
!1
	d38n	
 
 
 
   2 >@L LL)L7:L	hL L L L\Y Y Y Y<0; 0;	d38n	0; 0; 0; 0;f ;= I47	d4S>"	#   *I) IT#s(^0D I I I I;( ;tDcN7K ; ; ; ;>!,9&6XMN!,	d38n	!, !, !, !,F1 1I 1# 1~ 1 1 1 1fKtCy K K K K>d > > > >4 4x} 4S#X 4 4 4 4" " "( ( (
           rf   r  )yr  rS   r   r  rw   r   mathr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   r   redis.exceptionsr  r   redis.asyncior  redis.asyncio.clusterr   r  redis.clusterr   r   redisvl.query.queryr   redisvl.query.sqlr   redisvl.redis.utilsr   r   r   r   r   r   r   redisvl.typesr   r   r    redisvl.utils.utilsr!   r"   r#   !redis.commands.search.aggregationr$   redis.commands.search.documentr%   redis.commands.search.resultr&   r'   r(   redis_versionredis.clientr)   redisvl.utils.redis_protocolr*   
startswith%redis.commands.search.indexDefinitionr,   &redis.commands.search.index_definitionredisvl.exceptionsr-   r.   r/   r0   r1   redisvl.index.storager2   r3   r4   redisvl.queryr5   r6   r7   r8   r9   redisvl.query.aggregater:   redisvl.query.filterr;   redisvl.redis.connectionr<   r=   r>   r?   redisvl.redis.constantsr@   redisvl.schemarA   rB   redisvl.schema.fieldsrC   rD   rE   rF   redisvl.utils.logrG   r   r   r   "REQUIRED_MODULES_FOR_INTROSPECTIONrY   r6  r]   bytesr	  r|   r   r   r   r  rh   rf   rd   <module>rn     sV                                                          - - - - - - C C C C C C & & & & & & , , , , , , + + + + + + & & & & & &                  N M M M M M M M M M V V V V V V V V V V .AAAAAA777777333333------ . . . . . . % % % % % % = = = = = = =C              
 0 / / / / /              H G G G G G G G G G                9 8 8 8 8 8 1 1 1 1 1 1            : 9 9 9 9 9 3 3 3 3 3 3 3 3            ) ( ( ( ( (	H		  B  e$$5))& "
 	c9nd3c3u4556<=	? 
#y.	D3D3'D31<D3	$sCx.D3 D3 D3 D3N//'7/GR/	$sCx./ / / /8x
 x
 x
 x
 x
 x
 x
 x
vA A A A A/ A A AHz  z  z  z  z  z  z  z  z  z rf   