diff --git a/synapse/handlers/user_directory.py b/synapse/handlers/user_directory.py
index 0cf403f599..4a9565df93 100644
--- a/synapse/handlers/user_directory.py
+++ b/synapse/handlers/user_directory.py
@@ -40,6 +40,9 @@ class UserDirectoyHandler(object):
self.clock.call_later(0, self.notify_new_event)
+ def search_users(self, search_term, limit):
+ return self.store.search_user_dir(search_term, limit)
+
@defer.inlineCallbacks
def notify_new_event(self):
if self._is_processing:
diff --git a/synapse/storage/user_directory.py b/synapse/storage/user_directory.py
index d72b93b585..650c49982d 100644
--- a/synapse/storage/user_directory.py
+++ b/synapse/storage/user_directory.py
@@ -153,3 +153,38 @@ class UserDirectoryStore(SQLBaseStore):
return self._execute(
"get_current_state_deltas", self.cursor_to_dict, sql, prev_stream_id
)
+
+ @defer.inlineCallbacks
+ def search_user_dir(self, search_term, limit):
+ if isinstance(self.database_engine, PostgresEngine):
+ sql = """
+ SELECT user_id, display_name, avatar_url
+ FROM user_directory
+ WHERE vector @@ to_tsquery('english', ?)
+ ORDER BY ts_rank_cd(vector, to_tsquery('english', ?)) DESC
+ LIMIT ?
+ """
+ args = (search_term, search_term, limit + 1,)
+ elif isinstance(self.database_engine, Sqlite3Engine):
+ sql = """
+ SELECT user_id, display_name, avatar_url
+ FROM user_directory
+ WHERE value MATCH ?
+ ORDER BY rank(matchinfo(user_directory)) DESC
+ LIMIT ?
+ """
+ args = (search_term, limit + 1)
+ else:
+ # This should be unreachable.
+ raise Exception("Unrecognized database engine")
+
+ results = yield self._execute(
+ "search_user_dir", self.cursor_to_dict, sql, *args
+ )
+
+ limited = len(results) > limit
+
+ defer.returnValue({
+ "limited": limited,
+ "results": results,
+ })
|