@@ -26,7 +26,7 @@ class Field(object):
2626 def __init__ (self , name , * args ):
2727 self .name = name
2828 self .args = args
29-
29+
3030 def redis_args (self ):
3131 return [self .name ] + list (self .args )
3232
@@ -87,14 +87,15 @@ class TagField(Field):
8787 TagField is a tag-indexing field with simpler compression and tokenization.
8888 See http://redisearch.io/Tags/
8989 """
90- def __init__ (self , name , separator = ',' , no_index = False ):
90+
91+ def __init__ (self , name , separator = ',' , no_index = False ):
9192 args = [Field .TAG , Field .SEPARATOR , separator ]
9293
9394 if no_index :
9495 args .append (Field .NOINDEX )
9596
9697 Field .__init__ (self , name , * args )
97-
98+
9899
99100class Client (object ):
100101 """
@@ -108,6 +109,7 @@ class Client(object):
108109 ALTER_CMD = 'FT.ALTER'
109110 SEARCH_CMD = 'FT.SEARCH'
110111 ADD_CMD = 'FT.ADD'
112+ ADDHASH_CMD = "FT.ADDHASH"
111113 DROP_CMD = 'FT.DROP'
112114 EXPLAIN_CMD = 'FT.EXPLAIN'
113115 DEL_CMD = 'FT.DEL'
@@ -120,7 +122,6 @@ class Client(object):
120122 GET_CMD = 'FT.GET'
121123 MGET_CMD = 'FT.MGET'
122124
123-
124125 NOOFFSETS = 'NOOFFSETS'
125126 NOFIELDS = 'NOFIELDS'
126127 STOPWORDS = 'STOPWORDS'
@@ -156,6 +157,20 @@ def add_document(self, doc_id, nosave=False, score=1.0, payload=None,
156157 if self .current_chunk >= self .chunk_size :
157158 self .commit ()
158159
160+ def add_document_hash (
161+ self , doc_id , score = 1.0 , replace = False ,
162+ ):
163+ """
164+ Add a hash to the batch query
165+ """
166+ self .client ._add_document_hash (
167+ doc_id , conn = self .pipeline , score = score , replace = replace ,
168+ )
169+ self .current_chunk += 1
170+ self .total += 1
171+ if self .current_chunk >= self .chunk_size :
172+ self .commit ()
173+
159174 def commit (self ):
160175 """
161176 Manually commit and flush the batch indexing query
@@ -182,7 +197,7 @@ def batch_indexer(self, chunk_size=100):
182197 return Client .BatchIndexer (self , chunk_size = chunk_size )
183198
184199 def create_index (self , fields , no_term_offsets = False ,
185- no_field_flags = False , stopwords = None ):
200+ no_field_flags = False , stopwords = None ):
186201 """
187202 Create the search index. The index must not already exist.
188203
@@ -203,7 +218,7 @@ def create_index(self, fields, no_term_offsets=False,
203218 args += [self .STOPWORDS , len (stopwords )]
204219 if len (stopwords ) > 0 :
205220 args += list (stopwords )
206-
221+
207222 args .append ('SCHEMA' )
208223
209224 args += list (itertools .chain (* (f .redis_args () for f in fields )))
@@ -230,7 +245,7 @@ def drop_index(self):
230245 Drop the index if it exists
231246 """
232247 return self .redis .execute_command (self .DROP_CMD , self .index_name )
233-
248+
234249 def _add_document (self , doc_id , conn = None , nosave = False , score = 1.0 , payload = None ,
235250 replace = False , partial = False , language = None , no_create = False , ** fields ):
236251 """
@@ -260,6 +275,25 @@ def _add_document(self, doc_id, conn=None, nosave=False, score=1.0, payload=None
260275 args += list (itertools .chain (* fields .items ()))
261276 return conn .execute_command (* args )
262277
278+ def _add_document_hash (
279+ self , doc_id , conn = None , score = 1.0 , language = None , replace = False ,
280+ ):
281+ """
282+ Internal add_document_hash used for both batch and single doc indexing
283+ """
284+ if conn is None :
285+ conn = self .redis
286+
287+ args = [self .ADDHASH_CMD , self .index_name , doc_id , score ]
288+
289+ if replace :
290+ args .append ("REPLACE" )
291+
292+ if language :
293+ args += ["LANGUAGE" , language ]
294+
295+ return conn .execute_command (* args )
296+
263297 def add_document (self , doc_id , nosave = False , score = 1.0 , payload = None ,
264298 replace = False , partial = False , language = None , no_create = False , ** fields ):
265299 """
@@ -281,20 +315,44 @@ def add_document(self, doc_id, nosave=False, score=1.0, payload=None,
281315 - **fields** kwargs dictionary of the document fields to be saved and/or indexed.
282316 NOTE: Geo points shoule be encoded as strings of "lon,lat"
283317 """
284- return self ._add_document (doc_id , conn = None , nosave = nosave , score = score ,
318+ return self ._add_document (doc_id , conn = None , nosave = nosave , score = score ,
285319 payload = payload , replace = replace ,
286- partial = partial , language = language ,
287- no_create = no_create ,** fields )
320+ partial = partial , language = language ,
321+ no_create = no_create , ** fields )
322+
323+ def add_document_hash (
324+ self , doc_id , score = 1.0 , language = None , replace = False ,
325+ ):
326+ """
327+ Add a hash document to the index.
328+
329+ ### Parameters
330+
331+ - **doc_id**: the document's id. This has to be an existing HASH key in Redis that will hold the fields the index needs.
332+ - **score**: the document ranking, between 0.0 and 1.0
333+ - **replace**: if True, and the document already is in the index, we perform an update and reindex the document
334+ - **language**: Specify the language used for document tokenization.
335+ """
336+ return self ._add_document_hash (
337+ doc_id , conn = None , score = score , language = language , replace = replace ,
338+ )
288339
289- def delete_document (self , doc_id , conn = None ):
340+ def delete_document (self , doc_id , conn = None , delete_actual_document = False ):
290341 """
291342 Delete a document from index
292343 Returns 1 if the document was deleted, 0 if not
344+
345+ ### Parameters
346+
347+ - **delete_actual_document**: if set to True, RediSearch also delete the actual document if it is in the index
293348 """
349+ args = [self .DEL_CMD , self .index_name , doc_id ]
294350 if conn is None :
295351 conn = self .redis
352+ if delete_actual_document :
353+ args .append ('DD' )
296354
297- return conn .execute_command (self . DEL_CMD , self . index_name , doc_id )
355+ return conn .execute_command (* args )
298356
299357 def load_document (self , id ):
300358 """
@@ -315,12 +373,12 @@ def load_document(self, id):
315373 def get (self , * ids ):
316374 """
317375 Returns the full contents of multiple documents.
318-
376+
319377 ### Parameters
320-
378+
321379 - **ids**: the ids of the saved documents.
322380 """
323-
381+
324382 return self .redis .execute_command ('FT.MGET' , self .index_name , * ids )
325383
326384 def info (self ):
@@ -386,7 +444,8 @@ def aggregate(self, query):
386444 elif isinstance (query , Cursor ):
387445 has_schema = False
388446 has_cursor = True
389- cmd = [self .CURSOR_CMD , 'READ' , self .index_name ] + query .build_args ()
447+ cmd = [self .CURSOR_CMD , 'READ' ,
448+ self .index_name ] + query .build_args ()
390449 else :
391450 raise ValueError ('Bad query' , query )
392451
@@ -401,7 +460,7 @@ def aggregate(self, query):
401460 else :
402461 cursor = None
403462
404- if query ._with_schema :
463+ if isinstance ( query , AggregateRequest ) and query ._with_schema :
405464 schema = raw [0 ]
406465 rows = raw [2 :]
407466 else :
0 commit comments