Use full text search when using Postgres

On my laptop, this cuts search time from several seconds down to
a few hundred milliseconds.

If we want even more speed, we could store the ts_vector as a column
on the message database.  The Postgres documentation says this will
make "searches [...] faster, since it will not be necessary to redo
the to_tsvector calls to verify index matches."  Going this route
requires creating a trigger to automatically insert the appropriate
column when new rows are inserted.

Note that the full text index must be fully created before this
commit is deployed.  Full text search without an index is actually
significantly slower than using the LIKE operator.

(imported from commit ae74083da20d33aa2425d3e44fcdc19b160002ba)
This commit is contained in:
Zev Benjamin 2013-01-30 14:59:56 -05:00
parent c6d196a22f
commit 97851a93c4
1 changed files with 10 additions and 3 deletions

View File

@ -505,6 +505,8 @@ class NarrowBuilder(object):
# by name! The prefix 'by_' prevents it from colliding with builtin # by name! The prefix 'by_' prevents it from colliding with builtin
# Python __magic__ stuff. # Python __magic__ stuff.
method_name = 'by_' + operator.replace('-', '_') method_name = 'by_' + operator.replace('-', '_')
if method_name == 'by_search':
return self.do_search(query, operand)
method = getattr(self, method_name, None) method = getattr(self, method_name, None)
if method is None: if method is None:
raise BadNarrowOperator('unknown operator ' + operator) raise BadNarrowOperator('unknown operator ' + operator)
@ -556,10 +558,15 @@ class NarrowBuilder(object):
return ((Q(sender=narrow_profile) & Q(recipient=self_recipient)) | return ((Q(sender=narrow_profile) & Q(recipient=self_recipient)) |
(Q(sender=self.user_profile) & Q(recipient=narrow_recipient))) (Q(sender=self.user_profile) & Q(recipient=narrow_recipient)))
def by_search(self, operand): def do_search(self, query, operand):
return (Q(content__icontains=operand) | if "postgres" in settings.DATABASES["default"]["ENGINE"]:
sql = "to_tsvector('english', subject || ' ' || content) @@ to_tsquery('english', %s)"
return query.extra(where=[sql], params=[operand])
else:
return query.filter(Q(content__icontains=operand) |
Q(subject__icontains=operand)) Q(subject__icontains=operand))
def narrow_parameter(json): def narrow_parameter(json):
# FIXME: A hack to support old mobile clients # FIXME: A hack to support old mobile clients
if json == '{}': if json == '{}':