Skip to content

move sortable and no_index to the field field abstract… #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 32 additions & 41 deletions redisearch/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,81 +19,72 @@ class Field(object):
TAG = 'TAG'
SORTABLE = 'SORTABLE'
NOINDEX = 'NOINDEX'
SEPARATOR = 'SEPARATOR'
PHONETIC = 'PHONETIC'

def __init__(self, name, *args):
def __init__(self, name, *args, sortable=False, no_index=False):
self.name = name
self.args = args
self.args = list(args)
self.args_suffix = list()

if sortable:
self.args_suffix.append(Field.SORTABLE)
if no_index:
self.args_suffix.append(Field.NOINDEX)

if no_index and not sortable:
raise ValueError('Non-Sortable non-Indexable fields are ignored')

def append_arg(self, value):
self.args.append(value)

def redis_args(self):
return [self.name] + list(self.args)
return [self.name] + self.args + self.args_suffix


class TextField(Field):
"""
TextField is used to define a text field in a schema definition
"""
NOSTEM = 'NOSTEM'
PHONETIC = 'PHONETIC'

def __init__(self, name, weight=1.0, no_stem=False, phonetic_matcher=None, **kwargs):
Field.__init__(self, name, Field.TEXT, Field.WEIGHT, weight, **kwargs)

def __init__(self, name, weight=1.0, sortable=False, no_stem=False,
no_index=False, phonetic_matcher=None):
args = [Field.TEXT, Field.WEIGHT, weight]
if no_stem:
args.append(self.NOSTEM)
if sortable:
args.append(Field.SORTABLE)
if no_index:
args.append(self.NOINDEX)
Field.append_arg(self, self.NOSTEM)
if phonetic_matcher and phonetic_matcher in ['dm:en', 'dm:fr', 'dm:pt', 'dm:es']:
args.append(self.PHONETIC)
args.append(phonetic_matcher)

if no_index and not sortable:
raise ValueError('Non-Sortable non-Indexable fields are ignored')
Field.__init__(self, name, *args)
Field.append_arg(self, self.PHONETIC)
Field.append_arg(self, phonetic_matcher)


class NumericField(Field):
"""
NumericField is used to define a numeric field in a schema defintion
NumericField is used to define a numeric field in a schema definition
"""

def __init__(self, name, sortable=False, no_index=False):
args = [Field.NUMERIC]
if sortable:
args.append(Field.SORTABLE)
if no_index:
args.append(Field.NOINDEX)

if no_index and not sortable:
raise ValueError('Non-Sortable non-Indexable fields are ignored')

super(NumericField, self).__init__(name, *args)
def __init__(self, name, **kwargs):
Field.__init__(self, name, Field.NUMERIC, **kwargs)


class GeoField(Field):
"""
GeoField is used to define a geo-indexing field in a schema defintion
GeoField is used to define a geo-indexing field in a schema definition
"""

def __init__(self, name):
Field.__init__(self, name, Field.GEO)
def __init__(self, name, **kwargs):
Field.__init__(self, name, Field.GEO, **kwargs)


class TagField(Field):
SEPARATOR = 'SEPARATOR'

"""
TagField is a tag-indexing field with simpler compression and tokenization.
See http://redisearch.io/Tags/
"""

def __init__(self, name, separator=',', no_index=False):
args = [Field.TAG, Field.SEPARATOR, separator]

if no_index:
args.append(Field.NOINDEX)

Field.__init__(self, name, *args)
def __init__(self, name, separator=',', **kwargs):
Field.__init__(self, name, Field.TAG, self.SEPARATOR, separator, **kwargs)


class IndexDefinition(object):
Expand Down
35 changes: 25 additions & 10 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,27 +489,42 @@ def testNoIndex(self):
client = self.getCleanClient('idx')

client.create_index(
(TextField('f1', no_index=True, sortable=True), TextField('f2')))
(TextField('field'),
TextField('text', no_index=True, sortable=True),
NumericField('numeric', no_index=True, sortable=True),
GeoField('geo', no_index=True, sortable=True),
TagField('tag', no_index=True, sortable=True)))

client.add_document('doc1', f1='MarkZZ', f2='MarkZZ')
client.add_document('doc2', f1='MarkAA', f2='MarkAA')
client.add_document('doc1', field='aaa', text='1', numeric='1', geo='1,1', tag='1')
client.add_document('doc2', field='aab', text='2', numeric='2', geo='2,2', tag='2')

res = client.search(Query('@f1:Mark*'))
res = client.search(Query('@text:aa*'))
self.assertEqual(0, res.total)

res = client.search(Query('@f2:Mark*'))
res = client.search(Query('@field:aa*'))
self.assertEqual(2, res.total)

res = client.search(Query('@f2:Mark*').sort_by('f1', asc=False))
res = client.search(Query('*').sort_by('text', asc=False))
self.assertEqual(2, res.total)
self.assertEqual('doc2', res.docs[0].id)

res = client.search(Query('*').sort_by('text', asc=True))
self.assertEqual('doc1', res.docs[0].id)

res = client.search(Query('@f2:Mark*').sort_by('f1', asc=True))
self.assertEqual('doc2', res.docs[0].id)
res = client.search(Query('*').sort_by('numeric', asc=True))
self.assertEqual('doc1', res.docs[0].id)

res = client.search(Query('*').sort_by('geo', asc=True))
self.assertEqual('doc1', res.docs[0].id)

res = client.search(Query('*').sort_by('tag', asc=True))
self.assertEqual('doc1', res.docs[0].id)

# Ensure exception is raised for non-indexable, non-sortable fields
self.assertRaises(Exception, TextField,
'name', no_index=True, sortable=False)
self.assertRaises(Exception, TextField, 'name', no_index=True, sortable=False)
self.assertRaises(Exception, NumericField, 'name', no_index=True, sortable=False)
self.assertRaises(Exception, GeoField, 'name', no_index=True, sortable=False)
self.assertRaises(Exception, TagField, 'name', no_index=True, sortable=False)

def testPartial(self):
client = self.getCleanClient('idx')
Expand Down