@@ -857,3 +857,245 @@ def syndump(self):
857
857
""" # noqa
858
858
raw = self .execute_command (SYNDUMP_CMD , self .index_name )
859
859
return {raw [i ]: raw [i + 1 ] for i in range (0 , len (raw ), 2 )}
860
+
861
+
862
+ class AsyncSearchCommands (SearchCommands ):
863
+ async def info (self ):
864
+ """
865
+ Get info an stats about the the current index, including the number of
866
+ documents, memory consumption, etc
867
+
868
+ For more information https://oss.redis.com/redisearch/Commands/#ftinfo
869
+ """
870
+
871
+ res = await self .execute_command (INFO_CMD , self .index_name )
872
+ it = map (to_string , res )
873
+ return dict (zip (it , it ))
874
+
875
+ async def search (
876
+ self ,
877
+ query : Union [str , Query ],
878
+ query_params : Dict [str , Union [str , int , float ]] = None ,
879
+ ):
880
+ """
881
+ Search the index for a given query, and return a result of documents
882
+
883
+ ### Parameters
884
+
885
+ - **query**: the search query. Either a text for simple queries with
886
+ default parameters, or a Query object for complex queries.
887
+ See RediSearch's documentation on query format
888
+
889
+ For more information: https://oss.redis.com/redisearch/Commands/#ftsearch
890
+ """ # noqa
891
+ args , query = self ._mk_query_args (query , query_params = query_params )
892
+ st = time .time ()
893
+ res = await self .execute_command (SEARCH_CMD , * args )
894
+
895
+ if isinstance (res , Pipeline ):
896
+ return res
897
+
898
+ return Result (
899
+ res ,
900
+ not query ._no_content ,
901
+ duration = (time .time () - st ) * 1000.0 ,
902
+ has_payload = query ._with_payloads ,
903
+ with_scores = query ._with_scores ,
904
+ )
905
+
906
+ async def aggregate (
907
+ self ,
908
+ query : Union [str , Query ],
909
+ query_params : Dict [str , Union [str , int , float ]] = None ,
910
+ ):
911
+ """
912
+ Issue an aggregation query.
913
+
914
+ ### Parameters
915
+
916
+ **query**: This can be either an `AggregateRequest`, or a `Cursor`
917
+
918
+ An `AggregateResult` object is returned. You can access the rows from
919
+ its `rows` property, which will always yield the rows of the result.
920
+
921
+ For more information: https://oss.redis.com/redisearch/Commands/#ftaggregate
922
+ """ # noqa
923
+ if isinstance (query , AggregateRequest ):
924
+ has_cursor = bool (query ._cursor )
925
+ cmd = [AGGREGATE_CMD , self .index_name ] + query .build_args ()
926
+ elif isinstance (query , Cursor ):
927
+ has_cursor = True
928
+ cmd = [CURSOR_CMD , "READ" , self .index_name ] + query .build_args ()
929
+ else :
930
+ raise ValueError ("Bad query" , query )
931
+ if query_params is not None :
932
+ cmd += self .get_params_args (query_params )
933
+
934
+ raw = await self .execute_command (* cmd )
935
+ return self ._get_aggregate_result (raw , query , has_cursor )
936
+
937
+ async def spellcheck (self , query , distance = None , include = None , exclude = None ):
938
+ """
939
+ Issue a spellcheck query
940
+
941
+ ### Parameters
942
+
943
+ **query**: search query.
944
+ **distance***: the maximal Levenshtein distance for spelling
945
+ suggestions (default: 1, max: 4).
946
+ **include**: specifies an inclusion custom dictionary.
947
+ **exclude**: specifies an exclusion custom dictionary.
948
+
949
+ For more information: https://oss.redis.com/redisearch/Commands/#ftspellcheck
950
+ """ # noqa
951
+ cmd = [SPELLCHECK_CMD , self .index_name , query ]
952
+ if distance :
953
+ cmd .extend (["DISTANCE" , distance ])
954
+
955
+ if include :
956
+ cmd .extend (["TERMS" , "INCLUDE" , include ])
957
+
958
+ if exclude :
959
+ cmd .extend (["TERMS" , "EXCLUDE" , exclude ])
960
+
961
+ raw = await self .execute_command (* cmd )
962
+
963
+ corrections = {}
964
+ if raw == 0 :
965
+ return corrections
966
+
967
+ for _correction in raw :
968
+ if isinstance (_correction , int ) and _correction == 0 :
969
+ continue
970
+
971
+ if len (_correction ) != 3 :
972
+ continue
973
+ if not _correction [2 ]:
974
+ continue
975
+ if not _correction [2 ][0 ]:
976
+ continue
977
+
978
+ corrections [_correction [1 ]] = [
979
+ {"score" : _item [0 ], "suggestion" : _item [1 ]} for _item in _correction [2 ]
980
+ ]
981
+
982
+ return corrections
983
+
984
+ async def config_set (self , option , value ):
985
+ """Set runtime configuration option.
986
+
987
+ ### Parameters
988
+
989
+ - **option**: the name of the configuration option.
990
+ - **value**: a value for the configuration option.
991
+
992
+ For more information: https://oss.redis.com/redisearch/Commands/#ftconfig
993
+ """ # noqa
994
+ cmd = [CONFIG_CMD , "SET" , option , value ]
995
+ raw = await self .execute_command (* cmd )
996
+ return raw == "OK"
997
+
998
+ async def config_get (self , option ):
999
+ """Get runtime configuration option value.
1000
+
1001
+ ### Parameters
1002
+
1003
+ - **option**: the name of the configuration option.
1004
+
1005
+ For more information: https://oss.redis.com/redisearch/Commands/#ftconfig
1006
+ """ # noqa
1007
+ cmd = [CONFIG_CMD , "GET" , option ]
1008
+ res = {}
1009
+ raw = await self .execute_command (* cmd )
1010
+ if raw :
1011
+ for kvs in raw :
1012
+ res [kvs [0 ]] = kvs [1 ]
1013
+ return res
1014
+
1015
+ async def load_document (self , id ):
1016
+ """
1017
+ Load a single document by id
1018
+ """
1019
+ fields = await self .client .hgetall (id )
1020
+ f2 = {to_string (k ): to_string (v ) for k , v in fields .items ()}
1021
+ fields = f2
1022
+
1023
+ try :
1024
+ del fields ["id" ]
1025
+ except KeyError :
1026
+ pass
1027
+
1028
+ return Document (id = id , ** fields )
1029
+
1030
+ async def sugadd (self , key , * suggestions , ** kwargs ):
1031
+ """
1032
+ Add suggestion terms to the AutoCompleter engine. Each suggestion has
1033
+ a score and string.
1034
+ If kwargs["increment"] is true and the terms are already in the
1035
+ server's dictionary, we increment their scores.
1036
+
1037
+ For more information: https://oss.redis.com/redisearch/master/Commands/#ftsugadd
1038
+ """ # noqa
1039
+ # If Transaction is not False it will MULTI/EXEC which will error
1040
+ pipe = self .pipeline (transaction = False )
1041
+ for sug in suggestions :
1042
+ args = [SUGADD_COMMAND , key , sug .string , sug .score ]
1043
+ if kwargs .get ("increment" ):
1044
+ args .append ("INCR" )
1045
+ if sug .payload :
1046
+ args .append ("PAYLOAD" )
1047
+ args .append (sug .payload )
1048
+
1049
+ pipe .execute_command (* args )
1050
+
1051
+ return (await pipe .execute ())[- 1 ]
1052
+
1053
+ async def sugget (
1054
+ self , key , prefix , fuzzy = False , num = 10 , with_scores = False , with_payloads = False
1055
+ ):
1056
+ """
1057
+ Get a list of suggestions from the AutoCompleter, for a given prefix.
1058
+
1059
+ Parameters:
1060
+
1061
+ prefix : str
1062
+ The prefix we are searching. **Must be valid ascii or utf-8**
1063
+ fuzzy : bool
1064
+ If set to true, the prefix search is done in fuzzy mode.
1065
+ **NOTE**: Running fuzzy searches on short (<3 letters) prefixes
1066
+ can be very
1067
+ slow, and even scan the entire index.
1068
+ with_scores : bool
1069
+ If set to true, we also return the (refactored) score of
1070
+ each suggestion.
1071
+ This is normally not needed, and is NOT the original score
1072
+ inserted into the index.
1073
+ with_payloads : bool
1074
+ Return suggestion payloads
1075
+ num : int
1076
+ The maximum number of results we return. Note that we might
1077
+ return less. The algorithm trims irrelevant suggestions.
1078
+
1079
+ Returns:
1080
+
1081
+ list:
1082
+ A list of Suggestion objects. If with_scores was False, the
1083
+ score of all suggestions is 1.
1084
+
1085
+ For more information: https://oss.redis.com/redisearch/master/Commands/#ftsugget
1086
+ """ # noqa
1087
+ args = [SUGGET_COMMAND , key , prefix , "MAX" , num ]
1088
+ if fuzzy :
1089
+ args .append (FUZZY )
1090
+ if with_scores :
1091
+ args .append (WITHSCORES )
1092
+ if with_payloads :
1093
+ args .append (WITHPAYLOADS )
1094
+
1095
+ ret = await self .execute_command (* args )
1096
+ results = []
1097
+ if not ret :
1098
+ return results
1099
+
1100
+ parser = SuggestionParser (with_scores , with_payloads , ret )
1101
+ return [s for s in parser ]
0 commit comments