
    mBNj%                       d dl Z d dlZd dlmZmZmZmZmZ d dlm	Z	 d dl
mZmZ d dlmZmZmZmZ d dlmZmZ d dlmZmZmZmZmZ dd	lmZmZ d
dlmZm Z 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/ dZ0dZ1dZ2dZ3dZ4dZ5dZ6dZ7dZ8dZ9dZ:dZ;dZ<d Z=d!Z>d"Z?d#Z@d$ZAd%ZBd&ZCd'ZDd(ZEd)ZFd*ZGd+ZHd,ZId-ZJd.ZKd/ZLd0ZMd1ZNd2ZOd3ZPd4ZQd5ZRd6ZSd7ZTd8ZUd9ZVd:ZWd;ZXd<ZY G d= d>      ZZ G d? d@eZ      Z[y)A    N)AnyDictListOptionalUnion)pairs_to_dict)NEVER_DECODEPipeline)CombineResultsMethodHybridCursorQueryHybridPostProcessingConfigHybridQuery)HybridCursorResultHybridResult)check_protocol_versiondecode_field_valuedeprecated_functionexperimental_methodstr_if_bytes   )get_legacy_responsesget_protocol_version   )AggregateRequestAggregateResultCursor)Document)Field)IndexDefinition)ProfileInformation)Query)Result)SuggestionParserNUMERICz	FT.CREATEzFT.ALTERz	FT.SEARCHzFT.ADDz
FT.ADDHASHzFT.DROPINDEXz
FT.EXPLAINzFT.EXPLAINCLIzFT.DELzFT.AGGREGATEz
FT.PROFILEz	FT.CURSORzFT.SPELLCHECKz
FT.DICTADDz
FT.DICTDELzFT.DICTDUMPzFT.MGETz	FT.CONFIGz
FT.TAGVALSzFT.ALIASADDzFT.ALIASUPDATEzFT.ALIASDELzFT.INFOz	FT.SUGADDz	FT.SUGDELz	FT.SUGLENz	FT.SUGGETzFT.SYNUPDATEz
FT.SYNDUMPz	FT.HYBRID	NOOFFSETSNOFIELDSNOHLNOFREQSMAXTEXTFIELDS	TEMPORARY	STOPWORDSSKIPINITIALSCAN
WITHSCORESFUZZYWITHPAYLOADSc                      e Zd ZdZ eeeeee	h      Z
d Zd Zedd       Zed        Zd Zd Zd	 Zd
 Zd Zd Zd Zd Zd Zd Z eh d      Zed        Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$ed        Z%ed        Z&d Z'd Z(d  Z)d! Z*d" Z+edd#       Z,ed$        Z-d% Z.ed&        Z/d' Z0d( Z1d) Z2d* Z3dd+Z4	 	 	 	 	 	 	 	 	 dd,e5e6   d-e7d.e7d/e8e5e9      d0e8e:   d1e7d2e7d3e7fd4Z;d,e<e6e5e6   f   fd5Z=dd6e7fd7Z>	 	 	 	 	 	 	 	 dd8Z?	 dd9Z@ eAd:d;<      	 	 	 	 	 	 	 dd=e9d>e7d?eBd@e8e7   dAe7dBe7dCe8e9   dDe7d,e5e9   fdE       ZC eAd:d;<      ddF       ZD eAd:dG<      ddH       ZEddIe8eFe9eGf      fdJZH eAd:dG<      dK        ZIdL ZJdMe8eFe9e<e9eKeBeLf   f      fdNZMdMe8eFe9e<e9eKeBeLf   f      fdOZN	 ddPe<e9eOf   dMe<eFe9e<e9eKeBeLf   f   df   fdQZP eQ       	 	 	 	 	 ddPeRdRe8eS   dSe8eT   dTe8eFe9e<e9eKeBeLf   f      dUe8eK   dVe8eU   dWe<eVeWeXf   fdX       ZY	 ddPe<e9eOf   dMe8eFe9e<e9eKeBeLf   f      fdYZZdPe<e9eOf   fdZZ[	 ddPe<e\e]f   dMe8eFe9e<e9eKeBeLf   f      fd[Z^d\e5dPe<e\e]f   d]e7fd^Z_	 	 ddPe<eOe\f   d_e7dMe8eFe9e<e9eKeBeLf   f      dWe<e`e<eaebf   ecf   ecf   fd`ZdddaZedbe9dce5e9   fddZfdbe9dce5e9   fdeZgdbe9fdfZh eAdgdh<      die9dje9dWe7fdk       Zi eAdgdl<      die9dWe9fdm       Zjdne9fdoZkdpe9fdqZldpe9fdrZmdpe9fdsZndt Zodue9dWeKfdvZpdue9dwe9dWeKfdxZq	 	 	 	 ddue9dye9dze7d{eKd|e7d}e7dWe5er   fd~Zsdde9de7dce5e9   fdZtd Zuy)SearchCommandszSearch commands.c                    t         | j                  t        | j                  t        | j
                  t        | j                  t        | j                  t        | j                  t        | j                  t        | j                  i| _        t        | j"                  i| _        t         | j&                  t        | j(                  t        | j*                  t        | j,                  t        | j.                  t        | j0                  t        | j2                  t        | j4                  i| _        t        | j8                  t        | j:                  i| _        t         | j>                  t        | j                  t        | j@                  t        | j                  t        | jB                  t        | j                  t        | jD                  t        | jF                  i| _$        tK        | j6                        | _&        | jN                  | jL                  t         <   | jP                  | jL                  t        <   | jR                  | jL                  t        <   | jT                  | jL                  t        <   y)a  Build the per-protocol module callback maps.

        Called from ``Search.__init__``, ``Pipeline.__init__`` and
        ``AsyncPipeline.__init__`` so the mapping lives in a single place
        rather than being duplicated across all three classes.
        N)+INFO_CMD_parse_info
SEARCH_CMD_parse_search
HYBRID_CMD_parse_hybrid_searchAGGREGATE_CMD_parse_aggregatePROFILE_CMD_parse_profileSPELLCHECK_CMD_parse_spellcheck
CONFIG_CMD_parse_config_getSYNDUMP_CMD_parse_syndump_RESP2_MODULE_CALLBACKS!_parse_hybrid_search_resp3_native_RESP3_MODULE_CALLBACKS_parse_info_resp3_to_legacy_parse_search_resp3_parse_hybrid_search_resp3_parse_aggregate_resp3_parse_profile_resp3_parse_spellcheck_resp3!_parse_config_get_resp3_to_legacy_parse_syndump_resp3'_RESP3_TO_RESP2_LEGACY_MODULE_CALLBACKS&_pipeline_parse_search_resp3_to_legacy-_pipeline_parse_hybrid_search_resp3_to_legacy)_RESP3_TO_RESP2_LEGACY_PIPELINE_CALLBACKS_parse_info_unified_parse_hybrid_search_unified_parse_profile_unified_parse_config_get_unified_parse_syndump_unified_RESP2_UNIFIED_MODULE_CALLBACKSdict_RESP3_UNIFIED_MODULE_CALLBACKS_parse_info_resp3_parse_config_get_resp3_parse_profile_resp3_unified"_parse_hybrid_search_resp3_unified)selfs    o/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/redis/commands/search/commands.py_init_module_callbacksz%SearchCommands._init_module_callbacks^   s    d&&**11400,,D22..,,	(
$  >>(
$ d66007746622D88>>22	8
4 CCJJ:
6 d..**9940044D226644	0
, 04880
, :>9O9O,,X6;?;W;W,,Z8-- 	,,[9 33 	,,Z8    c                    || j                   v rd|vr|S t        | j                        }t        | j                        }|rx|dv r0|t        k(  rt        |      S | j                  j                  |      }nt        |d      r| j                  j                  |      }n_| j                  j                  |      }nCt        |d      r| j                  j                  |      }n| j                  j                  |      }||S  ||fi |S )Nquery)   3rd   )_QUERY_REQUIRED_CMDSr   clientr   r;   r    rE   getr   rN   rC   rY   rW   )r^   cmdreskwargsprotocollegacycbs          r_   _parse_resultszSearchCommands._parse_results   s    $+++v0EJ'4%dkk28#+%-c221155c:'!4AAEEcJ1155c:%h299==cB99==cB:J#   ra   Nc                     t        | t              s|S | j                  || j                  |j                         |            S N)
isinstancerX   rh   encode)mappingkeydefaults      r_   
_resp3_getzSearchCommands._resp3_get   s3    '4(N{{3CJJL' BCCra   c                     t        | t              s| S g }| j                         D ]0  \  }}|j                  t	        |             |j                  |       2 |S rq   )rr   rX   itemsappendr   )rt   flatru   values       r_   _flatten_resp3_mappingz%SearchCommands._flatten_resp3_mapping   sN    '4(N!--/JCKKS)*KK * ra   c           
         |j                  d      }|t        |t              s|S | j                  |dd      g}| j                  |dg       D ]  }|j	                  | j                  |d             |j
                  r!|j	                  | j                  |d             |j                  r!|j	                  | j                  |d             |j                  r|j	                  | j                  | j                  |di                     |S )	zDConvert RESP3 FT.SEARCH pipeline output to raw RESP2 pipeline shape.rc   total_resultsr   resultsidscorepayloadextra_attributes)	rh   rr   rX   rw   rz   _with_scores_with_payloads_no_contentr}   )r^   rj   rk   rc   outputitems         r_   rO   z5SearchCommands._pipeline_parse_search_resp3_to_legacy   s    

7#=
3 5J//#:;OOCB7DMM$//$56!!doodG<=##doodI>?$$//.@"E 8 ra   c                    t        |t              s|S |j                         D ci c]  \  }}t        |      | }}}d|v r$d|j	                  d      d|j	                  d      gS |j	                  dg       D cg c]%  }t        |t              r| j                  |      n|' }}d|j	                  dd      d|d|j	                  dg       d|j	                  dd      gS c c}}w c c}w )	zDConvert RESP3 FT.HYBRID pipeline output to raw RESP2 pipeline shape.cursorSEARCHVSIMr   r   r   warningsexecution_time)rr   rX   ry   r   rh   r}   )r^   rj   rk   ru   r|   r   r   s          r_   rP   z<SearchCommands._pipeline_parse_hybrid_search_resp3_to_legacy   s    #t$J:=))+F+JC|C %'+Fvcggh/II 	2.
. 2<D$1GD''-TQ. 	 

 GGOQ'GGJ#GG$a(	
 		
 G
s   C!;*C'c                 L    t        t        |      }t        t        ||            S rq   )mapr   rX   zip)r^   rj   rk   its       r_   r4   zSearchCommands._parse_info  s    s#CBK  ra   c           	          t        ||d   j                   |d   |d   j                  |d   j                  |d   j                        S )Nrc   duration)r   has_payloadwith_scoresfield_encodings)r"   r   r   r   _return_fields_decode_asr^   rj   rk   s      r_   r6   zSearchCommands._parse_search  sQ    w+++J'w66w44"7ODD
 	
ra   c           	         t        |d      }d|v r%t        t        |d         t        |d               S g }|d   D ]   }t        |d      }|j                  |       " t	        t        |d         ||d	   t        |d
               S )NTdecode_keysr   r   r   search_cursor_idvsim_cursor_idr   r   r   r   r   r   r   r   )r   r   intrz   r   float)r^   rj   rk   res_dictr   res_item	item_dicts          r_   r8   z#SearchCommands._parse_hybrid_search  s     $7v%!$Xh%7!8"8F#34 
 )+ !+H%hDAINN9% , h78j) *:!;<	
 	
ra   c                 4    | j                  ||d   |d         S )Nrc   
has_cursor)_get_aggregate_resultr   s      r_   r:   zSearchCommands._parse_aggregate&  s     ))#vg|@TUUra   c                     |d   }t        |t              r!| j                  |d   ||j                        }n5t	        |d   |j
                   |d   |j                  |j                        }|t        |d         fS )Nrc   r   r   r   r   r   r   )	rr   r   r   _cursorr"   r   r   r   r    )r^   rj   rk   rc   results        r_   r<   zSearchCommands._parse_profile)  s    we-.//Au}}MFA%%%
+!00!..F )#a&111ra   c                     i }|dk(  r|S |D ]X  }t        |t              r|dk(  rt        |      dk7  r(|d   s.|d   d   s7|d   D cg c]  }|d   |d   d c}||d   <   Z |S c c}w )Nr   rd   r   r   r   
suggestion)rr   r   len)r^   rj   rk   corrections_correction_items         r_   r>   z SearchCommands._parse_spellcheck8  s    !8K+s+q0@;1$q>q>!$$ JUUV+IW%(%(;+KA'5 < 	+s   
A)c                 B    |r|D ci c]  }|d   |d    c}S i S c c}w Nr   r    r^   rj   rk   kvss       r_   r@   z SearchCommands._parse_config_get]  s-    25#.#3AA#.=2=.s   c                 h    t        dt        |      d      D ci c]  }||   ||dz       c}S c c}w Nr   r   r   )ranger   )r^   rj   rk   is       r_   rB   zSearchCommands._parse_syndump`  s:    ,1!SXq,AB,AqAAE
",ABBBs   />   typeWEIGHTPHONETIC	SEPARATOR	attribute
identifierc                    i }g }t         j                  }d}|t        |       k  rbt        | |         }||v r+|dz   t        |       k  rt        | |dz            ||<   |dz  }n|j	                  |       |dz  }|t        |       k  rb||d<   |S )aC  Convert a RESP2 flat attribute list into a RESP3-style dict.

        RESP2 format: ``[identifier, name, attribute, alias, type, TEXT,
        WEIGHT, 1, SORTABLE, NOSTEM]``.
        RESP3 format: ``{"identifier": name, "attribute": alias, "type":
        "TEXT", "WEIGHT": "1", "flags": ["SORTABLE", "NOSTEM"]}``.
        r   r   r   flags)r1   _INFO_ATTR_PAIR_KEYSr   r   rz   )	attr_listr   r   	pair_keysr   ru   s         r_   _normalize_info_attributez(SearchCommands._normalize_info_attributek  s     "77	#i. y|,CiAEC	N$:*9QU+;<sQS!Q #i.   wra   c                     t        t        |      }t        t        ||            }d|v rJt	        |d   t
              r7|d   D cg c]%  }t	        |t
              r| j                  |      n|' c}|d<   |S c c}w )zParse FT.INFO into the unified shape with ``attributes`` as a
        list of dicts so RESP2 output matches RESP3 output.
        
attributes)r   r   rX   r   rr   listr   )r^   rj   rk   r   infoattrs         r_   rR   z"SearchCommands._parse_info_unified  s     s#CBK 4JtL/A4$H !.".D 9C48N..t4TXX."D 	"s   *A6c                    t        |d      }d|v r%t        t        |d         t        |d               S  | j                  di |}g }|d   D ]S  }t        |d      }|j	                  |j                         D 	ci c]  \  }}	|| j                  |	||       c}	}       U t        t        |d         ||d	   t        |d
               S c c}	}w )NTr   r   r   r   r   r   r   r   r   r   r   )	r   r   r   _hybrid_field_encodingsrz   ry   _decode_hybrid_field_valuer   r   )
r^   rj   rk   r   r   r   r   r   ru   r|   s
             r_   rS   z+SearchCommands._parse_hybrid_search_unified  s     $7v%!$Xh%7!8"8F#34 
 7$66@@(* +H%hDAINN '0oo&7&7
U 88_UU&7 , h78j) *:!;<	
 	
s   >Cc                 l   |d   }t        |t              r!| j                  |d   ||j                        }n5t	        |d   |j
                   |d   |j                  |j                        }|d   }t        |t              r(|r&t        |d   t        t        f      rt        |d      }|t        |      fS )zParse FT.PROFILE into ``(result, ProfileInformation)`` with
        the profile_data normalised to a dict on >= 7.9.0 servers.
        rc   r   r   r   r   Tr   )rr   r   r   r   r"   r   r   r   r   strbytesr   r    )r^   rj   rk   rc   r   profile_datas         r_   rT   z%SearchCommands._parse_profile_unified  s     we-.//Au}}MFA%%%
+!00!..F 1v |T*<?S%L9(4HL),777ra   c                 f    |si S |D ci c]  }t        |d         t        |d          c}S c c}w r   )r   r   s       r_   rU   z(SearchCommands._parse_config_get_unified  s9    IFIJcsSV$l3q6&::cJJJs   ".c                    |si S t        dt        |      d      D ci c]U  }t        ||         t        ||dz      t              r||dz      D cg c]  }t        |       c}nt        ||dz            W c}}S c c}w c c}}w r   )r   r   r   rr   r   )r^   rj   rk   r   ss        r_   rV   z%SearchCommands._parse_syndump_unified  s    I
 1c#h*	
 + Q #a!e*d+ =@AJ"GJq<?J"Gc!a%j)* +	
 	
"G
s   2BA<"B<Bc           
          |j                  d      }t        j                  ||j                  dd      t        |dd      t        |dd            S )	z4Parse RESP3 FT.SEARCH response into a Result object.rc   r   r   r   Fr   N)r   r   r   )rh   r"   
from_resp3getattr)r^   rj   rk   rc   s       r_   rG   z"SearchCommands._parse_search_resp3  sM    

7#  ZZ
A.~u=#E+EtL	
 	
ra   c                 Z   |j                  d      }|j                  dd      }d}|r+t        |t              r|d   }t        |      dkD  r|d   nd}n|}|i }|j	                         D ci c]  \  }}t        |      | }}}|j                  dg       D 	cg c]  }	t        |	       }
}	|j                  dd      }g }|j                  d	g       D ]  }|j	                         D ci c]  \  }}t        |      | }}}|j                  d
i       }g }|j	                         D ]'  \  }}|j                  |       |j                  |       ) |j                  |        d}|r%t        |t              r
||_        |}nt        |      }t        ||d||
      S c c}}w c c}	w c c}}w )zAParse RESP3 FT.AGGREGATE response into an AggregateResult object.rc   r   Fr   r   Nwarningr   r   r   )totalr   )
rh   rr   r   r   ry   r   rz   r   cidr   )r^   rj   rk   rc   r   	cursor_iddatakvwr   r   rowsresult_itemextra_attrsr{   r   s                    r_   rI   z%SearchCommands._parse_aggregate_resp3  s   

7#ZZe4
 	*S$/q6D"%c(Q,AAID<D 04zz|<|tq!Q"|<-1XXi-DE-DLO-DE!,88Ir2K:E:K:K:MN:M$!Q<?A-:MKN%//*<bAK D#))+1AA , KK 3 %(%		*tVTRR3 =E
 Os   ,FF")F'c                 j   |j                         D ci c]  \  }}t        |      | }}}d|v r%t        t        |d         t        |d               S g }|j	                  dg       D ]k  }t        |t              r=|j                  |j                         D ci c]  \  }}t        |      | c}}       P|j                  t        |d             m t        t        |j	                  dd	            ||j	                  d
g       t        |j	                  dd	                  S c c}}w c c}}w )a4  Parse RESP3 FT.HYBRID response into HybridResult/HybridCursorResult.

        Top-level keys are normalised to strings.  Values are preserved
        as delivered by the wire (bytes when ``NEVER_DECODE`` is set,
        strings otherwise) so byte/str semantics match the RESP2 legacy
        parser.
        r   r   r   r   r   Tr   r   r   r   r   r   )ry   r   r   r   rh   rr   rX   rz   r   r   r   )r^   rj   rk   r   r   r   r   s          r_   rH   z)SearchCommands._parse_hybrid_search_resp3  s    /2iik:kda|A!k:v%!$S]!3"3v;/ 
 )+	2.H(D)x~~?OP?Otq!Q 2?OPQ}X4HI	 / cggoq9:WWZ, )91!=>	
 	
 ;  Qs   D)D/c                 8   |j                         D ci c]  \  }}t        |      | }}}d|v r%t        t        |d         t        |d               S  | j                  di |}g }|j                  dg       D ]  }t        |t              rW|j                  |j                         D 	ci c]+  \  }}	t        |      | j                  |	t        |      |      - c}	}       jt        |d      }
|j                  |
j                         D 	ci c]  \  }}	|| j                  |	||       c}	}        t        t        |j                  dd	            ||j                  d
g       t        |j                  dd	                  S c c}}w c c}	}w c c}	}w )z=Parse RESP3 FT.HYBRID into the approved unified HybridResult.r   r   r   r   r   Tr   r   r   r   r   r   r   )ry   r   r   r   r   rh   rr   rX   rz   r   r   r   r   )r^   rj   rk   r   r   r   r   r   ru   r|   r   s              r_   r]   z1SearchCommands._parse_hybrid_search_resp3_unified0  s   .1iik:kda|A!k:v%!$S]!3"3v;/ 
 7$66@@(*	2.H(D)
 +3..*:	 +;JC %S)4+J+J!<#4o,  +;	 *(E	
 +4//*;	 +<JC T<<!3  +<	 /* cggoq9:WWZ, )91!=>	
 	
? ;s   F
-0FFc                      i }dD ]4  }| j                  |      }t        |dd       }|s$|j                  |       6 |xs d S )N)rc   post_processingr   )rh   r   update)rk   	encodingssource_namesourcesource_encodingss        r_   r   z&SearchCommands._hybrid_field_encodingsX  sN    	7KZZ,F&v/I4P  !12	 8
  D ra   c                 ,    |r||vr| S t        | ||      S rq   )r   )r|   ru   r   s      r_   r   z)SearchCommands._decode_hybrid_field_valueb  s     #_"<L!%o>>ra   c                    |j                         D ci c]  \  }}t        |      | }}}d|v r|S d|v rb|d   D cg c]L  }t        |t              r-|j                         D ci c]  \  }}t        |      | c}}nt	        |d      N c}}}|d<   d|v r|d   D cg c]  }t        |       c}|d<   |S c c}}w c c}}w c c}}}w c c}w )a[  Normalise RESP3 FT.HYBRID map keys while preserving native shape.

        ``protocol=3`` + ``legacy_responses=True`` keeps the RESP3 dict
        surface, but HYBRID uses ``NEVER_DECODE`` so result values mirror
        legacy RESP2 bytes. Decode only structural keys so callers can use
        the same native RESP3 key names as before.
        r   r   Tr   r   )ry   r   rr   rX   r   )r^   rj   rk   r   r   r   r   s          r_   rD   z0SearchCommands._parse_hybrid_search_resp3_nativeh  s     /2iik:kda|A!k:vJ
  	N	 +D dD) 15

=1a!#="4T:; +	C	N 8;JH1|AHC
O
 ; > Is#   B> (C
(C>C
$CC
c                    t        |t              s | j                  |fi |S |j                         D ci c]  \  }}t	        |      | }}}i }|j                  di       }|j                         D ]f  \  }}|s	g }	|D ]O  }
|
j                         D ]:  \  }}t        |      }|j                  d      r|dd }|	j                  ||d       < Q |	sb|	||<   h |S c c}}w )a#  Parse RESP3 FT.SPELLCHECK response into unified format.

        RESP3 format:
            {"results": {"term": [{"suggestion": score}, ...], ...}}
        Unified format (matches RESP2 parsed output):
            {"term": [{"score": score_str, "suggestion": suggestion}, ...], ...}
        r   z.0Nr   )	rr   rX   r>   ry   r   rh   r   endswithrz   )r^   rj   rk   r   r   r   r   termsuggestionsterm_correctionssuggestion_dictr   r   	score_strs                 r_   rK   z&SearchCommands._parse_spellcheck_resp3  s     #t$)4))#888 /2iik:kda|A!k:'')R(!(D+!#.)8)>)>)@%J !$E
I ))$/$-crN	 %++"+:F *A $/  $4D!' "1( / ;s   Cc           	         |d   }|j                  d      }||j                  d      }||j                  d      }||j                  d      }||j                  d      }|j                  d      }||j                  d      }||j                  d	      }||j                  d
      }||j                  d      }t        |t              rt        |      |d}t        |t              r(| j                  ||t        |j                              }n3t        j                  ||j                  dd      t        |dd            }| j                  |      }||fS )zExtract ``(result, profile_data_dict)`` from a RESP3 FT.PROFILE
        response.  ``profile_data_dict`` has its keys/values normalised
        to strings but is otherwise left as the native RESP3 dict.
        rc   Resultss   Resultsr   s   resultsr   Profiles   Profileprofiles   profiler   )r   r   rc   r   r   r   F)r   r   )rh   rr   r   r   r   rI   boolr   r"   r   r   _to_string_recursive)r^   rj   rk   rc   results_datar   r   s          r_   _extract_resp3_profile_partsz+SearchCommands._extract_resp3_profile_parts  se   
 w wwy)77:.L779-L77:.L771:Lwwy)77:.L779-L77:.L771:L
 lD)!$\!2'L e-.00Ed5==6I 1 F &&J2#E>5AF
 00>|##ra   c                     t        |t              r | j                  |fi |S  | j                  |fi |\  }}t        |t              rd|v xs d|v }| j                  ||      }|t        |      fS )a  Parse RESP3 FT.PROFILE response into ``(result, ProfileInformation)``.

        RESP3 format (aligned, RediSearch >= MOD-6816):
            {"Results": {search/aggregate result dict},
             "Profile": {profile information dict}}

        Older RediSearch versions may return a list (same as RESP2) even
        when the connection uses RESP3.  In that case we delegate to the
        RESP2 ``_parse_profile`` parser.
        ShardsCoordinator)flat_top)rr   r   r<   r  rX   _resp3_profile_dict_to_listr    )r^   rj   rk   r   r   r  s         r_   rJ   z#SearchCommands._parse_profile_resp3  s     c4 &4&&s5f55@t@@OO lD)</P=L3PH;;x < L ),777ra   c                     t        |t              r | j                  |fi |S  | j                  |fi |\  }}t        |t              rd|v sd|v s| j                  |      }|t        |      fS )a  Parse RESP3 FT.PROFILE for the unified shape.

        Redis < 7.9.0 returns RESP2 profile data as nested list-of-pairs,
        while RESP3 returns the same data as a dict.  Convert that pre-7.9
        RESP3 dict back to the RESP2 list shape so the unified surface is
        protocol-independent.  Redis >= 7.9.0 coordinator profiles contain
        ``Shards``/``Coordinator`` keys and stay as dicts, matching the
        RESP2 unified parser.
        r  r  )rr   r   rT   r  rX   r  r    )r^   rj   rk   r   r   s        r_   r\   z+SearchCommands._parse_profile_resp3_unified  s|     c4 .4..s=f==@t@@OOlD)$(E;;LIL),777ra   c                 2    d dfd	 | d      S )a*  Convert a RESP3 profile dict into the RESP2 wire list shape.

        Pre-7.9.0 servers serialise the RESP2 profile as a list of
        ``[key, value]`` pairs at the top level, with nested structures
        as flat alternating key-value lists.  Post-7.9.0 servers serialise
        the top level itself as a flat ``[key, value, key, value]`` list
        (with ``"Shards"``/``"Coordinator"`` keys).  ``flat_top`` selects
        between these two top-level shapes; nested dicts always use the
        flat alternating form.

        Key structural difference: when a dict value is a list of dicts
        (e.g. ``"Child iterators": [{...}, {...}]``), RESP2 expands each
        dict as a separate sibling element in the parent flat list rather
        than keeping them nested inside a single value.
        c                 T    t        | t              xr | xr t        | d   t              S )Nr   )rr   r   rX   )objs    r_   _is_list_of_dictszESearchCommands._resp3_profile_dict_to_list.<locals>._is_list_of_dicts  s$    c4(MSMZA5MMra   c                 8   t        | t              r|rp	sng }| j                         D ]W  \  }}|g} |      r|D ]  }|j                   |              n|j                   |             |j                  |       Y |S g }| j                         D ]T  \  }}|j                  |        |      r|D ]  }|j                   |              >|j                   |             V |S t        | t              r| D cg c]
  } |       c}S | S c c}w rq   )rr   rX   ry   rz   r   )
r  	top_levelr   r   r   entryr   _convertr  r  s
          r_   r  z<SearchCommands._resp3_profile_dict_to_list.<locals>._convert  s   #t$XF #		1!",Q/() %Xd^ < )* "LL!5e, !, "MF #		1a(,Q/() &htn = )* #MM(1+6 !, "MC&36734377J 8s   DT)r  Fr   )r   r  r  r  s    `@@r_   r  z*SearchCommands._resp3_profile_dict_to_list
  s    $	N	6 --ra   c                 |   t        | t              rt        |       S t        | t              rR| j	                         D ci c]6  \  }}t        |t              rt        |      n|t
        j                  |      8 c}}S t        | t              r#| D cg c]  }t
        j                  |       c}S | S c c}}w c c}w )zRecursively convert bytes keys/values to strings in nested
        structures.  Non-bytes scalars (int, float, None, bool) pass
        through unchanged.
        )rr   r   r   rX   ry   r1   r  r   )r  r   r   r   s       r_   r  z#SearchCommands._to_string_recursive>  s     c5!$$c4 
  IIK	 (DAq $.a#7QQ"77:; (	  c4 JMN#$N77=#NN
 Os   ;B3B9c                 $    | j                  |      S )z;Parse RESP3 FT.INFO response, normalising bytes to strings.r  r   s      r_   rZ   z SearchCommands._parse_info_resp3Q  s    ((--ra   c                     g }| j                  d      xs g }| j                         D ]-  \  }}|dk(  r|j                  |       |j                  |       / |j                  |       |S )zConvert a RESP3-style attribute dict back into the RESP2 flat
        list (key-value pairs followed by bare flag tokens).
        r   )rh   ry   rz   extend)	attr_dictr{   r   r   r   s        r_   _flatten_info_attributez&SearchCommands._flatten_info_attributeU  sd    
 g&,"OO%DAqG|KKNKKN	 &
 	Era   c                     | j                  |      }|j                  d      }t        |t              r4|D cg c]%  }t        |t              r| j                  |      n|' c}|d<   |S c c}w )zParse RESP3 FT.INFO into the legacy RESP2 flat shape so
        ``legacy_responses=True`` on a RESP3 wire matches RESP2 output.
        r   )r  rh   rr   r   rX   r  )r^   rj   rk   r   attrsr   s         r_   rF   z*SearchCommands._parse_info_resp3_to_legacyd  sw     ((-&eT" ""!D 7At6L,,T2RVV!"D 	"s   *A)c                     |si S |j                         D ci c]  \  }}t        |      t        |       c}}S c c}}w )zAParse RESP3 FT.CONFIG GET response, normalising bytes to strings.)ry   r   )r^   rj   rk   r   r   s        r_   r[   z&SearchCommands._parse_config_get_resp3q  s9    I=@YY[I[TQQa0[IIIs   ;c                      |rt        |      S i S )z>Parse RESP3 FT.CONFIG GET back to the RESP2 legacy dict shape.)rX   r   s      r_   rL   z0SearchCommands._parse_config_get_resp3_to_legacyw  s    tCy'R'ra   c                 ,    |si S | j                  |      S )z>Parse RESP3 FT.SYNDUMP response, normalising bytes to strings.r  r   s      r_   rM   z#SearchCommands._parse_syndump_resp3{  s    I((--ra   c                 (    | j                  | |      S )zT
        Create a new batch indexer from the client with a given chunk size
        )
chunk_size)BatchIndexer)r^   r   s     r_   batch_indexerzSearchCommands.batch_indexer  s       * ==ra   fieldsno_term_offsetsno_field_flags	stopwords
definitionno_highlightno_term_frequenciesskip_initial_scanc                 6   t         | j                  g}|||j                  z  }|r|j                  t               |6t        |t              r&|j                  t               |j                  |       |r|j                  t               |r|j                  t               |r|j                  t               |	r|j                  t               |
r|j                  t               |Kt        |t        t        t        f      r0|t         t#        |      gz  }t#        |      dkD  r|t        |      z  }|j                  d       	 |t        t%        j&                  d |D               z  } | j,                  | S # t(        $ r ||j+                         z  }Y -w xY w)a  
        Creates the search index. The index must not already exist.

        For more information, see https://redis.io/commands/ft.create/

        Args:
            fields: A list of Field objects.
            no_term_offsets: If `true`, term offsets will not be saved in the index.
            no_field_flags: If true, field flags that allow searching in specific fields
                            will not be saved.
            stopwords: If provided, the index will be created with this custom stopword
                       list. The list can be empty.
            definition: If provided, the index will be created with this custom index
                        definition.
            max_text_fields: If true, indexes will be encoded as if there were more than
                             32 text fields, allowing for additional fields beyond 32.
            temporary: Creates a lightweight temporary index which will expire after the
                       specified period of inactivity. The internal idle timer is reset
                       whenever the index is searched or added to.
            no_highlight: If true, disables highlighting support. Also implied by
                          `no_term_offsets`.
            no_term_frequencies: If true, term frequencies will not be saved in the
                                 index.
            skip_initial_scan: If true, the initial scan and indexing will be skipped.

        r   SCHEMAc              3   <   K   | ]  }|j                           y wrq   
redis_args.0fs     r_   	<genexpr>z.SearchCommands.create_index.<locals>.<genexpr>       *J6a1<<>6   )
CREATE_CMD
index_nameargsrz   r)   rr   r   r*   r%   r'   r&   r(   r,   r   tuplesetr+   r   	itertoolschain	TypeErrorr/  execute_command)r^   r#  r$  r%  r&  r'  max_text_fields	temporaryr(  r)  r*  r8  s               r_   create_indexzSearchCommands.create_index  sS   N DOO,!JOO#DKK& Z	3%?KK	"KK	"KK	"KKKK!KK KK( Z	D%;M%NYI//D9~!Y'H	(D*J6*JKLLD $t##T**  	(F%%''D	(s   %E9 9FFc                     t         | j                  ddg}	 |t        t        j                  d |D               z  } | j                  | S # t
        $ r ||j                         z  }Y -w xY w)a  
        Alter the existing search index by adding new fields. The index
        must already exist.

        ### Parameters:

        - **fields**: a list of Field objects to add for the index

        For more information see `FT.ALTER <https://redis.io/commands/ft.alter>`_.
        r,  ADDc              3   <   K   | ]  }|j                           y wrq   r.  r0  s     r_   r3  z2SearchCommands.alter_schema_add.<locals>.<genexpr>  r4  r5  )	ALTER_CMDr7  r   r;  r<  r=  r/  r>  )r^   r#  r8  s      r_   alter_schema_addzSearchCommands.alter_schema_add  sr     4??He<	(D*J6*JKLLD $t##T**  	(F%%''D	(s   %A
 
A)(A)delete_documentsc                     t         | j                  g}t        |t              r|du rdnd}|r|j	                  |        | j
                  | S )ai  
        Drop the index if it exists.
        Replaced `drop_index` in RediSearch 2.0.
        Default behavior was changed to not delete the indexed documents.

        ### Parameters:

        - **delete_documents**: If `True`, all documents will be deleted.

        For more information see `FT.DROPINDEX <https://redis.io/commands/ft.dropindex>`_.
        TDD )DROPINDEX_CMDr7  rr   r   rz   r>  )r^   rG  r8  
delete_strs       r_   	dropindexzSearchCommands.dropindex  sX     t/ *D16F$6N  	 KK
##t##T**ra   c
                    |s|	rd}t         | j                  ||g}|r|j                  d       |"|j                  d       |j                  |       |r7|j                  d       |r|j                  d       |	r|j                  d       |r|d|gz  }|j                  d       |t        t	        j
                  |
j                                z  }| |j                  | S  | j                  | S )	zS
        Internal add_document used for both batch and single doc indexing
        TNOSAVEPAYLOADREPLACEPARTIALNOCREATELANGUAGEFIELDS)ADD_CMDr7  rz   r   r;  r<  ry   r>  )r^   doc_idconnnosaver   r   replacepartiallanguage	no_creater#  r8  s               r_   _add_documentzSearchCommands._add_document  s    " iG&%8KK!KK	"KK KK	"I&J'Z**DHY__flln566'4''..#t##T**ra   c                     t         | j                  ||g}|r|j                  d       |r|d|gz  }| |j                  | S  | j                  | S )zX
        Internal add_document_hash used for both batch and single doc indexing
        rQ  rT  )ADDHASH_CMDr7  rz   r>  )r^   rW  rX  r   r\  rZ  r8  s          r_   _add_document_hashz!SearchCommands._add_document_hash$  sc     T__fe<KK	"Z**D'4''..#t##T**ra   z2.0.0z2deprecated since redisearch 2.0, call hset insteadversionreasonrW  rY  r   r   rZ  r[  r\  r]  c	                 :     | j                   |fd|||||||d|	S )a  
        Add a single document to the index.

        Args:

            doc_id: the id of the saved document.
            nosave: if set to true, we just index the document, and don't
                      save a copy of it. This means that searches will just
                      return ids.
            score: the document ranking, between 0.0 and 1.0
            payload: optional inner-index payload we can save for fast
                     access in scoring functions
            replace: if True, and the document already is in the index,
                     we perform an update and reindex the document
            partial: if True, the fields specified will be added to the
                       existing document.
                       This has the added benefit that any fields specified
                       with `no_index`
                       will not be reindexed again. Implies `replace`
            language: Specify the language used for document tokenization.
            no_create: if True, the document is only updated and reindexed
                         if it already exists.
                         If the document does not exist, an error will be
                         returned. Implies `replace`
            fields: kwargs dictionary of the document fields to be saved
                    and/or indexed.
                    NOTE: Geo points should be encoded as strings of "lon,lat"
        N)rX  rY  r   r   rZ  r[  r\  r]  )r^  )
r^   rW  rY  r   r   rZ  r[  r\  r]  r#  s
             r_   add_documentzSearchCommands.add_document8  sD    V "t!!

 
 	
ra   c                 .    | j                  |d|||      S )a  
        Add a hash document to the index.

        ### Parameters

        - **doc_id**: the document's id. This has to be an existing HASH key
                      in Redis that will hold the fields the index needs.
        - **score**:  the document ranking, between 0.0 and 1.0
        - **replace**: if True, and the document already is in the index, we
                      perform an update and reindex the document
        - **language**: Specify the language used for document tokenization.
        N)rX  r   r\  rZ  )ra  )r^   rW  r   r\  rZ  s        r_   add_document_hashz SearchCommands.add_document_hashp  s'      &&UXw ' 
 	
ra   zdeprecated since redisearch 2.0c                     t         | j                  |g}|r|j                  d       | |j                  | S  | j                  | S )a  
        Delete a document from index
        Returns 1 if the document was deleted, 0 if not

        ### Parameters

        - **delete_actual_document**: if set to True, RediSearch also delete
                                      the actual document if it is in the index
        rI  )DEL_CMDr7  rz   r>  )r^   rW  rX  delete_actual_documentr8  s        r_   delete_documentzSearchCommands.delete_document  sO     &1!KK'4''..#t##T**ra   r   c                    | j                   j                  |      }|j                         D ci c]%  \  }}t        |      t	        |t        |      |      ' }}}	 |d= t        dd|i|S c c}}w # t
        $ r Y w xY w)
        Load a single document by id

        - **field_encodings**: optional dict mapping field names to encodings.
          If a field's encoding is ``None`` the raw bytes value is preserved
          (useful for binary data such as vectors).
        r   r   rg   hgetallry   r   r   KeyErrorr   r^   r   r   r#  r   r   s         r_   load_documentzSearchCommands.load_document  s     $$R( 
&1 O/<?OTT& 	 

	t (2(((
  		s   *A-A3 3	A?>A?c                 F     | j                   t        | j                  g| S )z
        Returns the full contents of multiple documents.

        ### Parameters

        - **ids**: the ids of the saved documents.

        )r>  MGET_CMDr7  )r^   idss     r_   rh   zSearchCommands.get  s"     $t##HdooDDDra   c                 n    | j                  t        | j                        }| j                  t        |      S )
        Get info an stats about the the current index, including the number of
        documents, memory consumption, etc

        For more information see `FT.INFO <https://redis.io/commands/ft.info>`_.
        r>  r3   r7  ro   r^   rj   s     r_   r   zSearchCommands.info  s-     ""8T__=""8S11ra   query_paramsc                     |g S g }t        |      dkD  rh|j                  d       |j                  t        |      dz         |j                         D ]'  \  }}|j                  |       |j                  |       ) |S )Nr   PARAMSr   )r   rz   ry   )r^   r{  r8  ru   r|   s        r_   get_params_argszSearchCommands.get_params_args  sy     I|q KK!KKL)A-.*002
UC E" 3 ra   c                     | j                   g}t        |t              rt        |      }t        |t              st	        dt        |             ||j                         z  }|| j                  |      z  }||fS )NzBad query type )r7  rr   r   r!   
ValueErrorr   get_argsr~  )r^   rc   r{  r8  s       r_   _mk_query_argszSearchCommands._mk_query_args  ss      eS!%LE%'tE{m<==  $$\22U{ra   rc   c                    | j                  ||      \  }}t        j                         }i }t        t	        | j
                        d      s	d|t        <   t        | t              r
||d<   d|d<    | j                  t        g|i |}t        |t              r|S | j                  t        ||t        j                         |z
  dz        S )	  
        Search the index for a given query, and return a result of documents

        ### Parameters

        - **query**: the search query. Either a text for simple queries with
                     default parameters, or a Query object for complex queries.
                     See RediSearch's documentation on query format

        For more information see `FT.SEARCH <https://redis.io/commands/ft.search>`_.
        r{  rd   Trc   r   r        @@rc   r   r  time	monotonicr   r   rg   r	   rr   r
   r>  r5   ro   r^   rc   r{  r8  stoptionsrj   s          r_   searchzSearchCommands.search  s      ))%l)Ke^^%&:4;;&GK$(GL!dH%$GG"#GJ"d"":@@@c8$J""5DNN4Dr4IV3S # 
 	
ra   combine_methodr   params_substitutiontimeoutr   returnc                 H   | j                   }i }t        |g}	|	j                  |j                                |r|	j                  |j                                |r$|	j                  |j	                                ||d<   |r |	j                  | j                  |             |r|	j                  d|f       |r$d|d<   |	j                  |j	                                d|t        <   ||d<    | j                  |	i |}
t        |
t              r|
S  | j                  t        |
fi |S )M  
        Execute a hybrid search using both text and vector queries

        Args:
            - **query**: HybridQuery object
                        Contains the text and vector queries
            - **combine_method**: CombineResultsMethod object
                        Contains the combine method and parameters
            - **post_processing**: HybridPostProcessingConfig object
                        Contains the post processing configuration
            - **params_substitution**: Dict[str, Union[str, int, float, bytes]]
                        Contains the parameters substitution
            - **timeout**: int - contains the timeout in milliseconds
            - **cursor**: HybridCursorQuery object - contains the cursor configuration


        For more information see `FT.SEARCH <https://redis.io/commands/ft.hybrid>`.
        r   TIMEOUTTr   rc   r7  r7   r  r  
build_argsr~  r	   r>  rr   r
   ro   r^   rc   r  r   r  r  r   indexr  piecesrj   s              r_   hybrid_searchzSearchCommands.hybrid_search  s   8 e$enn&'MM.1134MM/4467)8G%&MM$../BCDMM9g./ $GHMM&++-.
 !% "d""F6g6c8$J"t"":s>g>>ra   c                 \    | j                  ||      \  }} | j                  t        g| S )zReturns the execution plan for a complex query.

        For more information see `FT.EXPLAIN <https://redis.io/commands/ft.explain>`_.
        r  )r  r>  EXPLAIN_CMD)r^   rc   r{  r8  
query_texts        r_   explainzSearchCommands.explain@  s6      ..u<.Pj#t##K7$77ra   c                     t        d      )Nz#EXPLAINCLI will not be implemented.)NotImplementedError)r^   rc   s     r_   explain_clizSearchCommands.explain_cliL  s    !"GHHra   c                    t        |t              r9t        |j                        }t        | j
                  g|j                         z   }nCt        |t              r'd}t        d| j
                  g|j                         z   }nt        d|      || j                  |      z  } | j                  | }| j                  t        |||      S )  
        Issue an aggregation query.

        ### Parameters

        **query**: This can be either an `AggregateRequest`, or a `Cursor`

        An `AggregateResult` object is returned. You can access the rows from
        its `rows` property, which will always yield the rows of the result.

        For more information see `FT.AGGREGATE <https://redis.io/commands/ft.aggregate>`_.
        TREAD	Bad queryr   rr   r   r   r   r9   r7  r  r   
CURSOR_CMDr  r~  r>  ro   r^   rc   r{  r   ri   raws         r_   	aggregatezSearchCommands.aggregateO  s    " e-.emm,J $//2U5E5E5GGCv&Jvt7%:J:J:LLC[%00t##L11"d""C(""3e
 # 
 	
ra   r  r   c                     |r1t        |t              r|d   |_        |}nt        |d         }|d   }nd }t        |t              r|j                  r|d   }|dd  }nd }|dd  }t        |||      S )Nr   r   r   )rr   r   r   r   _with_schemar   )r^   r  rc   r   r   schemar   s          r_   r   z$SearchCommands._get_aggregate_resulto  s     %(F	Aa&CFe-.53E3EVFqr7DFqr7DtVV44ra   limitedc                    t        j                         }t        | j                  dg}|r|j	                  d       |j	                  d       t        |t              rd|d<   ||j                         z  }nHt        |t              r-d|d<   ||j                         z  }|| j                  |      z  }nt        d       | j                  | }| j                  t        ||t        j                         |z
  dz  	      S )
a  
        Performs a search or aggregate command and collects performance
        information.

        ### Parameters

        **query**: This can be either an `AggregateRequest` or `Query`.
        **limited**: If set to True, removes details of reader iterator.
        **query_params**: Define one or more value parameters.
        Each parameter has a name and a value.

        rJ  LIMITEDQUERY	AGGREGATEr   r   z5Must provide AggregateRequest object or Query object.r  r  )r  r  r;   r7  rz   rr   r   r  r!   r  r~  r  r>  ro   )r^   rc   r  r{  r  ri   rj   s          r_   r   zSearchCommands.profile  s    * ^^DOOR0JJy!

7e-. CF5##%%Cu%CF5>>##C4''55CTUU"d""C(""ET^^5E5Jf4T # 
 	
ra   c                     t         | j                  |g}|r|j                  d|g       |r|j                  dd|g       |r|j                  dd|g        | j                  | }| j	                  t         |      S )a  
        Issue a spellcheck query

        Args:

            query: search query.
            distance: the maximal Levenshtein distance for spelling
                       suggestions (default: 1, max: 4).
            include: specifies an inclusion custom dictionary.
            exclude: specifies an exclusion custom dictionary.

        For more information see `FT.SPELLCHECK <https://redis.io/commands/ft.spellcheck>`_.
        DISTANCETERMSINCLUDEEXCLUDEr=   r7  r  r>  ro   r^   rc   distanceincludeexcluderi   rj   s          r_   
spellcheckzSearchCommands.spellcheck  sy     t6JJ
H-.JJG45JJG45"d""C("">377ra   nametermsc                 R    t         |g}|j                  |        | j                  | S )zAdds terms to a dictionary.

        ### Parameters

        - **name**: Dictionary name.
        - **terms**: List of items for adding to the dictionary.

        For more information see `FT.DICTADD <https://redis.io/commands/ft.dictadd>`_.
        )DICT_ADD_CMDr  r>  r^   r  r  ri   s       r_   dict_addzSearchCommands.dict_add  -     T"

5#t##S))ra   c                 R    t         |g}|j                  |        | j                  | S )a  Deletes terms from a dictionary.

        ### Parameters

        - **name**: Dictionary name.
        - **terms**: List of items for removing from the dictionary.

        For more information see `FT.DICTDEL <https://redis.io/commands/ft.dictdel>`_.
        )DICT_DEL_CMDr  r>  r  s       r_   dict_delzSearchCommands.dict_del  r  ra   c                 0    t         |g} | j                  | S )zDumps all terms in the given dictionary.

        ### Parameters

        - **name**: Dictionary name.

        For more information see `FT.DICTDUMP <https://redis.io/commands/ft.dictdump>`_.
        )DICT_DUMP_CMDr>  )r^   r  ri   s      r_   	dict_dumpzSearchCommands.dict_dump  s!     d##t##S))ra   8.0.0Ddeprecated since Redis 8.0, call config_set from core module insteadoptionr|   c                 >    t         d||g} | j                  | }|dk(  S )  Set runtime configuration option.

        ### Parameters

        - **option**: the name of the configuration option.
        - **value**: a value for the configuration option.

        For more information see `FT.CONFIG SET <https://redis.io/commands/ft.config-set>`_.
        SETOKr?   r>  r^   r  r|   ri   r  s        r_   
config_setzSearchCommands.config_set  s.     5&%0"d""C(d{ra   Ddeprecated since Redis 8.0, call config_get from core module insteadc                 ^    t         d|g} | j                  | }| j                  t         |      S )Get runtime configuration option value.

        ### Parameters

        - **option**: the name of the configuration option.

        For more information see `FT.CONFIG GET <https://redis.io/commands/ft.config-get>`_.
        GETr?   r>  ro   r^   r  ri   rj   s       r_   
config_getzSearchCommands.config_get  s5     5&)"d""C("":s33ra   tagfieldc                 D    | j                  t        | j                  |      S )z
        Return a list of all possible tag values

        ### Parameters

        - **tagfield**: Tag field name

        For more information see `FT.TAGVALS <https://redis.io/commands/ft.tagvals>`_.
        )r>  TAGVALS_CMDr7  )r^   r  s     r_   tagvalszSearchCommands.tagvals  s     ##K(KKra   aliasc                 D    | j                  t        || j                        S )z
        Alias a search index - will fail if alias already exists

        ### Parameters

        - **alias**: Name of the alias to create

        For more information see `FT.ALIASADD <https://redis.io/commands/ft.aliasadd>`_.
        )r>  ALIAS_ADD_CMDr7  r^   r  s     r_   aliasaddzSearchCommands.aliasadd$  s     ##M5$//JJra   c                 D    | j                  t        || j                        S )z
        Updates an alias - will fail if alias does not already exist

        ### Parameters

        - **alias**: Name of the alias to create

        For more information see `FT.ALIASUPDATE <https://redis.io/commands/ft.aliasupdate>`_.
        )r>  ALIAS_UPDATE_CMDr7  r  s     r_   aliasupdatezSearchCommands.aliasupdate1  s     ##$4eT__MMra   c                 .    | j                  t        |      S )z
        Removes an alias to a search index

        ### Parameters

        - **alias**: Name of the alias to delete

        For more information see `FT.ALIASDEL <https://redis.io/commands/ft.aliasdel>`_.
        )r>  ALIAS_DEL_CMDr  s     r_   aliasdelzSearchCommands.aliasdel>  s     ##M599ra   c                 h   | j                  d      }|D ]  }t        ||j                  |j                  g}|j	                  d      r|j                  d       |j                  r,|j                  d       |j                  |j                          |j                  |   |j                         d   S )aJ  
        Add suggestion terms to the AutoCompleter engine. Each suggestion has
        a score and string.
        If kwargs["increment"] is true and the terms are already in the
        server's dictionary, we increment their scores.

        For more information see `FT.SUGADD <https://redis.io/commands/ft.sugadd/>`_.
        Ftransaction	incrementINCRrP  	pipelineSUGADD_COMMANDstringr   rh   rz   r   r>  executer^   ru   r   rk   pipesugr8  s          r_   sugaddzSearchCommands.sugaddJ  s     }}}/C"CSYY?Dzz+&F#{{I&CKK( D  $'  ||~b!!ra   ru   c                 .    | j                  t        |      S )z
        Return the number of entries in the AutoCompleter index.

        For more information see `FT.SUGLEN <https://redis.io/commands/ft.suglen>`_.
        )r>  SUGLEN_COMMAND)r^   ru   s     r_   suglenzSearchCommands.suglena  s     ##NC88ra   r  c                 0    | j                  t        ||      S )z
        Delete a string from the AutoCompleter index.
        Returns 1 if the string was found and deleted, 0 otherwise.

        For more information see `FT.SUGDEL <https://redis.io/commands/ft.sugdel>`_.
        )r>  SUGDEL_COMMAND)r^   ru   r  s      r_   sugdelzSearchCommands.sugdeli  s     ##NC@@ra   prefixfuzzynumr   with_payloadsc                    t         ||d|g}|r|j                  t               |r|j                  t               |r|j                  t                | j
                  | }g }	|s|	S t        |||      }
|
D cg c]  }| c}S c c}w )t  
        Get a list of suggestions from the AutoCompleter, for a given prefix.

        Parameters:

        prefix : str
            The prefix we are searching. **Must be valid ascii or utf-8**
        fuzzy : bool
            If set to true, the prefix search is done in fuzzy mode.
            **NOTE**: Running fuzzy searches on short (<3 letters) prefixes
            can be very
            slow, and even scan the entire index.
        with_scores : bool
            If set to true, we also return the (refactored) score of
            each suggestion.
            This is normally not needed, and is NOT the original score
            inserted into the index.
        with_payloads : bool
            Return suggestion payloads
        num : int
            The maximum number of results we return. Note that we might
            return less. The algorithm trims irrelevant suggestions.

        Returns:

        list:
             A list of Suggestion objects. If with_scores was False, the
             score of all suggestions is 1.

        For more information see `FT.SUGGET <https://redis.io/commands/ft.sugget>`_.
        MAXSUGGET_COMMANDrz   r.   r-   r/   r>  r#   )r^   ru   r  r  r  r   r  r8  rj   r   parserr   s               r_   suggetzSearchCommands.suggetr  s    P VUC8KKKK
#KK%"d""D)N!+}cB!"6a6"""s   7	Bgroupidskipinitialc                     t         | j                  |g}|r|j                  dg       |j                  |        | j                  | S )a  
        Updates a synonym group.
        The command is used to create or update a synonym group with
        additional terms.
        Only documents which were indexed after the update will be affected.

        Parameters:

        groupid :
            Synonym group id.
        skipinitial : bool
            If set to true, we do not scan and index.
        terms :
            The terms.

        For more information see `FT.SYNUPDATE <https://redis.io/commands/ft.synupdate>`_.
        r,   )SYNUPDATE_CMDr7  r  r>  )r^   r  r  r  ri   s        r_   	synupdatezSearchCommands.synupdate  sF    $ doow7JJ)*+

5#t##S))ra   c                 n    | j                  t        | j                        }| j                  t        |      S )a  
        Dumps the contents of a synonym group.

        The command is used to dump the synonyms data structure.
        Returns a list of synonym terms and their synonym group ids.

        For more information see `FT.SYNDUMP <https://redis.io/commands/ft.syndump>`_.
        )r>  rA   r7  ro   rz  s     r_   syndumpzSearchCommands.syndump  s-     "";@"";44ra   rq   r  )d   )	FFNNFNFFF)NF      ?NFFNF)Nr  NF)Fr  NFFNF)r  NF)NFNNNNN)FNNNNF
   FF)v__name__
__module____qualname____doc__	frozensetr5   r9   r  r7   r;   rf   r`   ro   staticmethodrw   r}   rO   rP   r4   r6   r8   r:   r<   r>   r@   rB   r   r   rR   rS   rT   rU   rV   rG   rI   rH   r]   r   r   rD   rK   r  rJ   r\   r  r  rZ   r  rF   r[   rL   rM   r"  r   r   r   r   r   r   rA  r   rF  rM  r^  ra  r   r   rf  rh  rl  r   r   rs  rh   r   r   r   r~  r  r!   r  r   r   r   r   r   r   r   r
   r  r  r  r   r   r  r   r9  r"   r   r    r   r  r  r  r  r  r  r  r  r  r  r  r  r   r#   r  r  r  r   ra   r_   r1   r1   R   s    %	]J
KHM
^!. D D
  *
2!

,V2#J>C %N  .
68<K


+S^
:&
P ! ! ? ?
2$P/$b888( /. /.f  $.  J(.> !&$)-04"$)"'D+UD+ D+ 	D+
 DI&D+ _-D+ D+ "D+  D+L+uUDK-?'@ +(+$ +8 (+V DI+(  T "&"&3
3
 3
 	3

 $3
 3
 3
 3-3
 3
 s)3
3
j  T

" 1RS+ T+&)$sCx.1I )* 1RS
E T
E	2$T#uS#ue5K/L*L%MN#+DeCeU<R6S1S,T#U& OS!
S%Z !
 DeCeU,B&C!CDdJK!
F  :>@DRV!%.27?7? !!567? ""<=	7?
 &d3c3u6L0M+M&NO7? #7? *+7? 
|/9	:7? 7?x LP
8S%Z 
8 tCsC/E)F$FGH
8IsEz!2 I LP
%v-.
 tCsC/E)F$FGH
@55 %&6&> ?5MQ52 KO	)
U,,-)
 )
 tCsC/E)F$FGH	)

 
eFO+,.@@A	
)
V88*S *$s) **S *$s) *
*c 
* U S T 	 U4 4 4	4L LKc KN N
:c 
:".9# 9# 9A# As As A !#6#6# 6# 	6#
 6# 6# 6# 
	6#p* *4 *c *0
5ra   r1   c                      e Zd Zd Z	 d!deeef   deeeeee	e
ef   f      fdZ e       	 	 	 	 	 d"dedee   dee   deeeeee	e
ef   f      d	ee	   d
ee   deeeef   fd       Z	 d!deeef   deeeeee	e
ef   f      fdZd#dZ edd      dededefd       Z edd      dedefd       Zd!deeeef      fdZd Z 	 	 	 	 d$dededede	dedede!e"   fd Z#y)%AsyncSearchCommandsc                    K   | j                  t        | j                         d{   }| j                  t        |      S 7 w)rx  Nry  rz  s     r_   r   zAsyncSearchCommands.info  s:      ((4??CC""8S11 Ds   $AAANrc   r{  c                   K   | j                  ||      \  }}t        j                         }i }t        t	        | j
                        d      s	d|t        <   t        | t              r
||d<   d|d<    | j                  t        g|i | d{   }t        |t              r|S | j                  t        ||t        j                         |z
  dz  	      S 7 Gw)
r  r  rd   Trc   r   r   Nr  r  r  r  s          r_   r  zAsyncSearchCommands.search  s       ))%l)Ke^^%&:4;;&GK$(GL!dH%$GG"#GJ(D((FdFgFFc8$J""5DNN4Dr4IV3S # 
 	
 Gs   BCCACr  r   r  r  r   r  c                 d  K   | j                   }i }t        |g}	|	j                  |j                                |r|	j                  |j                                |r$|	j                  |j	                                ||d<   |r |	j                  | j                  |             |r|	j                  d|f       |r$d|d<   |	j                  |j	                                d|t        <   ||d<    | j                  |	i | d{   }
t        |
t              r|
S  | j                  t        |
fi |S 7 .w)r  r   r  Tr   rc   Nr  r  s              r_   r  z!AsyncSearchCommands.hybrid_search  s    8 e$enn&'MM.1134MM/4467)8G%&MM$../BCDMM9g./ $GHMM&++-.
 !% (D((&<G<<c8$J"t"":s>g>> =s   C=D0?D. /D0c                   K   t        |t              r9t        |j                        }t        | j
                  g|j                         z   }nCt        |t              r'd}t        d| j
                  g|j                         z   }nt        d|      || j                  |      z  } | j                  |  d{   }| j                  t        |||      S 7 w)r  Tr  r  Nr   r  r  s         r_   r  zAsyncSearchCommands.aggregate8  s     " e-.emm,J $//2U5E5E5GGCv&Jvt7%:J:J:LLC[%00t##L11(D((#..""3e
 # 
 	
 /s   B3C5C6Cc                   K   t         | j                  |g}|r|j                  d|g       |r|j                  dd|g       |r|j                  dd|g        | j                  |  d{   }| j	                  t         |      S 7 w)a  
        Issue a spellcheck query

        ### Parameters

        **query**: search query.
        **distance***: the maximal Levenshtein distance for spelling
                       suggestions (default: 1, max: 4).
        **include**: specifies an inclusion custom dictionary.
        **exclude**: specifies an exclusion custom dictionary.

        For more information see `FT.SPELLCHECK <https://redis.io/commands/ft.spellcheck>`_.
        r  r  r  r  Nr  r  s          r_   r  zAsyncSearchCommands.spellcheckX  s      t6JJ
H-.JJG45JJG45(D((#.."">377 /s   A'B)B*Br  r  rb  r  r|   c                 Z   K   t         d||g} | j                  |  d{   }|dk(  S 7 	w)r  r  Nr  r  r  s        r_   r  zAsyncSearchCommands.config_sett  s:      5&%0(D((#..d{ /s   +)
+r  c                 ~   K   t         d|g}i } | j                  |  d{   }| j                  t         |      S 7 w)r  r  Nr  r  s       r_   r  zAsyncSearchCommands.config_get  sF      5&)(D((#.."":s33 /s   =;=r   c                    K   | j                   j                  |       d{   }|j                         D ci c]%  \  }}t        |      t	        |t        |      |      ' }}}	 |d= t        dd|i|S 7 Uc c}}w # t
        $ r Y  w xY ww)rn  Nr   r   ro  rr  s         r_   rs  z!AsyncSearchCommands.load_document  s      {{**2.. 
&1 O/<?OTT& 	 

	t (2((( /
  		sD   BA7B*A9#B'A? *B9B?	BB
BBc                   K   | j                  d      }|D ]  }t        ||j                  |j                  g}|j	                  d      r|j                  d       |j                  r,|j                  d       |j                  |j                          |j                  |   |j                          d{   d   S 7 w)aI  
        Add suggestion terms to the AutoCompleter engine. Each suggestion has
        a score and string.
        If kwargs["increment"] is true and the terms are already in the
        server's dictionary, we increment their scores.

        For more information see `FT.SUGADD <https://redis.io/commands/ft.sugadd>`_.
        Fr  r  r  rP  Nr  r  r  s          r_   r  zAsyncSearchCommands.sugadd  s      }}}/C"CSYY?Dzz+&F#{{I&CKK( D  $'  lln$b))$s   B4C 6B>7C ru   r  r  r  r   r  c                 ,  K   t         ||d|g}|r|j                  t               |r|j                  t               |r|j                  t                | j
                  |  d{   }g }	|s|	S t        |||      }
|
D cg c]  }| c}S 7 'c c}w w)r  r  Nr  )r^   ru   r  r  r  r   r  r8  retr   r
  r   s               r_   r  zAsyncSearchCommands.sugget  s     P VUC8KKKK
#KK%(D(($//N!+}cB!"6a6"" 0 #s$   A#B%B&B	B
BBrq   r  r  r  )$r  r  r  r   r   r   r!   r   r   r   r   r   r  r   r   r   r   r   r   r   r
   r  r   r   r  r  r   r   r  r  r   rs  r  r   r#   r  r   ra   r_   r   r     s    	2 LP!
S%Z !
 tCsC/E)F$FGH!
F  :>@DRV!%.27?7? !!567? ""<=	7?
 &d3c3u6L0M+M&NO7? #7? *+7? 
|/9	:7? 7?x LP
_f,-
 tCsC/E)F$FGH
@88 Us 3 4 	 U4s 4s 4	4)xS#X7O )**6 !#6#6# 6# 	6#
 6# 6# 6# 
	6#ra   r   )\r;  r  typingr   r   r   r   r   redis._parsers.helpersr   redis.clientr	   r
   "redis.commands.search.hybrid_queryr   r   r   r   #redis.commands.search.hybrid_resultr   r   redis.utilsr   r   r   r   r   helpersr   r   aggregationr   r   r   documentr   fieldr   index_definitionr   profile_informationr    rc   r!   r   r"   r   r#   r$   r6  rE  r5   rV  r`  rK  r  EXPLAINCLI_CMDrj  r9   r;   r  r=   r  r  r  ru  r?   r  r  r  r  r3   r  r  r  r	  r  rA   r7   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r1   r   r   ra   r_   <module>r9     sF     3 3 0 /  Q  A 
   - 3   (

	

 

 
# 
	
		#
z5 z5z3k#. k#ra   