From 97851a93c4f60a85ae1818800b409c72802d8c7d Mon Sep 17 00:00:00 2001 From: Zev Benjamin Date: Wed, 30 Jan 2013 14:59:56 -0500 Subject: [PATCH] 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) --- zephyr/views.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/zephyr/views.py b/zephyr/views.py index b78ec78fd7..32b5e841da 100644 --- a/zephyr/views.py +++ b/zephyr/views.py @@ -505,6 +505,8 @@ class NarrowBuilder(object): # by name! The prefix 'by_' prevents it from colliding with builtin # Python __magic__ stuff. method_name = 'by_' + operator.replace('-', '_') + if method_name == 'by_search': + return self.do_search(query, operand) method = getattr(self, method_name, None) if method is None: raise BadNarrowOperator('unknown operator ' + operator) @@ -556,9 +558,14 @@ class NarrowBuilder(object): return ((Q(sender=narrow_profile) & Q(recipient=self_recipient)) | (Q(sender=self.user_profile) & Q(recipient=narrow_recipient))) - def by_search(self, operand): - return (Q(content__icontains=operand) | - Q(subject__icontains=operand)) + def do_search(self, query, 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)) + def narrow_parameter(json): # FIXME: A hack to support old mobile clients