Skip to content

Commit 77ec182

Browse files
FT.CREATE - support MAXTEXTFIELDS, TEMPORARY, NOHL, NOFREQS, SKIPINITIALSCAN (#144)
* add tags to client creat_index function * test expire * test skip initial scan and summarization disabled * add testMaxTextFields
1 parent 54e4bca commit 77ec182

File tree

2 files changed

+111
-3
lines changed

2 files changed

+111
-3
lines changed

redisearch/client.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ class IndexDefinition(object):
107107
IndexDefinition is used to define a index definition for automatic indexing on Hash or Json update.
108108
"""
109109

110-
def __init__(self, prefix=[], filter=None, language_field=None, language=None, score_field=None, score=1.0, payload_field=None, index_type=None):
110+
def __init__(self, prefix=[], filter=None, language_field=None, language=None, score_field=None,
111+
score=1.0, payload_field=None, index_type=None):
111112
args = []
112113

113114
if index_type is IndexType.HASH:
@@ -182,7 +183,12 @@ class Client(object):
182183

183184
NOOFFSETS = 'NOOFFSETS'
184185
NOFIELDS = 'NOFIELDS'
186+
NOHL = 'NOHL'
187+
NOFREQS = 'NOFREQS'
188+
MAXTEXTFIELDS = 'MAXTEXTFIELDS'
189+
TEMPORARY = 'TEMPORARY'
185190
STOPWORDS = 'STOPWORDS'
191+
SKIPINITIALSCAN = 'SKIPINITIALSCAN'
186192

187193
class BatchIndexer(object):
188194
"""
@@ -256,7 +262,9 @@ def batch_indexer(self, chunk_size=100):
256262
return Client.BatchIndexer(self, chunk_size=chunk_size)
257263

258264
def create_index(self, fields, no_term_offsets=False,
259-
no_field_flags=False, stopwords=None, definition=None):
265+
no_field_flags=False, stopwords=None, definition=None,
266+
max_text_fields=False, temporary=None, no_highlight=False,
267+
no_term_frequencies=False, skip_initial_scan=False):
260268
"""
261269
Create the search index. The index must not already exist.
262270
@@ -266,15 +274,33 @@ def create_index(self, fields, no_term_offsets=False,
266274
- **no_term_offsets**: If true, we will not save term offsets in the index
267275
- **no_field_flags**: If true, we will not save field flags that allow searching in specific fields
268276
- **stopwords**: If not None, we create the index with this custom stopword list. The list can be empty
277+
- **max_text_fields**: If true, we will encode indexes as if there were more than 32 text fields,
278+
which allows you to add additional fields (beyond 32).
279+
- **temporary**: Create a lightweight temporary index which will expire after the specified period of
280+
inactivity (in seconds). The internal idle timer is reset whenever the index is searched or added to.
281+
- **no_highlight**: If true, disabling highlighting support. Also implied by no_term_offsets.
282+
- **no_term_frequencies**: If true, we avoid saving the term frequencies in the index.
283+
- **skip_initial_scan**: If true, we do not scan and index.
269284
"""
270285

271286
args = [self.CREATE_CMD, self.index_name]
272287
if definition is not None:
273-
args += definition.args
288+
args += definition.args
289+
if max_text_fields:
290+
args.append(self.MAXTEXTFIELDS)
291+
if temporary is not None and isinstance(temporary, int):
292+
args.append(self.TEMPORARY)
293+
args.append(temporary)
274294
if no_term_offsets:
275295
args.append(self.NOOFFSETS)
296+
if no_highlight:
297+
args.append(self.NOHL)
276298
if no_field_flags:
277299
args.append(self.NOFIELDS)
300+
if no_term_frequencies:
301+
args.append(self.NOFREQS)
302+
if skip_initial_scan:
303+
args.append(self.SKIPINITIALSCAN)
278304
if stopwords is not None and isinstance(stopwords, (list, tuple, set)):
279305
args += [self.STOPWORDS, len(stopwords)]
280306
if len(stopwords) > 0:

test/test.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,28 @@ def testReplace(self):
300300
self.assertEqual(1, res.total)
301301
self.assertEqual('doc1', res.docs[0].id)
302302

303+
def testExpire(self):
304+
client = self.getCleanClient('idx')
305+
client.create_index((TextField('txt', sortable=True),), temporary=4)
306+
307+
redis_client = redis.client.Redis()
308+
ttl = redis_client.execute_command('ft.debug', 'TTL', 'idx')
309+
self.assertTrue(ttl > 2)
310+
while ttl > 2:
311+
ttl = redis_client.execute_command('ft.debug', 'TTL', 'idx')
312+
time.sleep(0.01)
313+
314+
# add document - should reset the ttl
315+
client.add_document('doc', txt='foo bar', text='this is a simple test')
316+
ttl = redis_client.execute_command('ft.debug', 'TTL', 'idx')
317+
self.assertTrue(ttl > 2)
318+
try:
319+
while True:
320+
ttl = redis_client.execute_command('ft.debug', 'TTL', 'idx')
321+
time.sleep(0.5)
322+
except redis.exceptions.ResponseError:
323+
self.assertEqual(ttl, 0)
324+
303325
def testStopwords(self):
304326
# Creating a client with a given index name
305327
client = self.getCleanClient('idx')
@@ -314,6 +336,18 @@ def testStopwords(self):
314336
self.assertEqual(0, res1.total)
315337
self.assertEqual(1, res2.total)
316338

339+
def testSkipInitialScan(self):
340+
client = self.getCleanClient('idx')
341+
client.redis.hset("doc1", "foo", "bar")
342+
q = Query('@foo:bar')
343+
344+
client1 = self.getCleanClient('idx1')
345+
client1.create_index((TextField('foo'),))
346+
self.assertEqual(1, client1.search(q).total)
347+
client2 = self.getCleanClient('idx2')
348+
client2.create_index((TextField('foo'),), skip_initial_scan=True)
349+
self.assertEqual(0, client2.search(q).total)
350+
317351
def testFilters(self):
318352
conn = self.redis()
319353

@@ -602,6 +636,25 @@ def testSummarize(self):
602636
self.assertEqual('ACT I SCENE I. London. The palace. Enter <b>KING</b> <b>HENRY</b>, LORD JOHN OF LANCASTER, the EARL of WESTMORELAND, SIR... ',
603637
doc.txt)
604638

639+
def testSummarizeDisabled(self):
640+
# test NOOFFSETS
641+
client = self.getCleanClient('idx')
642+
client.create_index((TextField('txt'),), no_term_offsets=True)
643+
client.add_document('doc1', txt='foo bar')
644+
with self.assertRaises(Exception) as context:
645+
client.search(Query('foo').summarize(fields=['txt']))
646+
self.assertEqual('Cannot use highlight/summarize because NOOFSETS was specified at index level',
647+
str(context.exception))
648+
649+
# test NOHL
650+
client = self.getCleanClient('idx')
651+
client.create_index((TextField('txt'),), no_highlight=True)
652+
client.add_document('doc1', txt='foo bar')
653+
with self.assertRaises(Exception) as context:
654+
client.search(Query('foo').summarize(fields=['txt']))
655+
self.assertEqual('Cannot use highlight/summarize because NOOFSETS was specified at index level',
656+
str(context.exception))
657+
605658
def testAlias(self):
606659
conn = self.redis()
607660
with conn as r:
@@ -735,6 +788,35 @@ def testTextFieldSortableNostem(self):
735788
self.assertIn('SORTABLE', response['attributes'][0])
736789
self.assertIn('NOSTEM', response['attributes'][0])
737790

791+
def testMaxTextFields(self):
792+
conn = self.redis()
793+
794+
with conn as r:
795+
# Creating a client
796+
client = Client('idx1', port=conn.port)
797+
client.redis.flushdb()
798+
799+
# Creating the index definition
800+
client.create_index((TextField('f0'),))
801+
# Fill the index with fields
802+
for x in range(1, 32):
803+
client.alter_schema_add((TextField('f{}'.format(x)),))
804+
# OK for now.
805+
806+
# Should be too many indexes
807+
with self.assertRaises(redis.ResponseError):
808+
client.alter_schema_add((TextField('f{}'.format(x)),))
809+
810+
# Creating new client
811+
client = Client('idx2', port=conn.port)
812+
client.redis.flushdb()
813+
814+
# Creating the index definition
815+
client.create_index((TextField('f0'),), max_text_fields=True)
816+
# Fill the index with fields
817+
for x in range(1, 50):
818+
client.alter_schema_add((TextField('f{}'.format(x)),))
819+
738820
def testAlterSchemaAdd(self):
739821
conn = self.redis()
740822

0 commit comments

Comments
 (0)