Split out directory and search tables

pull/2252/head
Erik Johnston 2017-05-31 15:23:49 +01:00
parent dc51af3d03
commit 5d79d728f5
2 changed files with 56 additions and 29 deletions

View File

@ -28,30 +28,33 @@ CREATE TABLE user_directory_stream_pos (
); );
INSERT INTO user_directory_stream_pos (stream_id) VALUES (null); INSERT INTO user_directory_stream_pos (stream_id) VALUES (null);
"""
POSTGRES_TABLE = """
CREATE TABLE user_directory ( CREATE TABLE user_directory (
user_id TEXT NOT NULL, user_id TEXT NOT NULL,
room_id TEXT NOT NULL, -- A room_id that we know is public room_id TEXT NOT NULL, -- A room_id that we know is public
display_name TEXT, display_name TEXT,
avatar_url TEXT, avatar_url TEXT
vector tsvector
); );
CREATE INDEX user_directory_fts_idx ON user_directory USING gin(vector);
CREATE INDEX user_directory_room_idx ON user_directory(room_id); CREATE INDEX user_directory_room_idx ON user_directory(room_id);
CREATE INDEX user_directory_user_idx ON user_directory(user_id); CREATE INDEX user_directory_user_idx ON user_directory(user_id);
""" """
SQLITE_TABLE = """ POSTGRES_TABLE = """
CREATE VIRTUAL TABLE user_directory CREATE TABLE user_directory_search (
USING fts4 ( user_id, room_id, display_name, avatar_url, value ); user_id TEXT NOT NULL,
vector tsvector
);
CREATE INDEX user_directory_room_idx ON user_directory(room_id); CREATE INDEX user_directory_search_fts_idx ON user_directory_search USING gin(vector);
CREATE INDEX user_directory_user_idx ON user_directory(user_id); CREATE INDEX user_directory_search_user_idx ON user_directory_search(user_id);
"""
SQLITE_TABLE = """
CREATE VIRTUAL TABLE user_directory_search
USING fts4 ( user_id, value );
""" """

View File

@ -61,9 +61,8 @@ class UserDirectoryStore(SQLBaseStore):
# We weight the loclpart most highly, then display name and finally # We weight the loclpart most highly, then display name and finally
# server name # server name
sql = """ sql = """
INSERT INTO user_directory INSERT INTO user_directory_search(user_id, vector)
(user_id, room_id, display_name, avatar_url, vector) VALUES (?,
VALUES (?,?,?,?,
setweight(to_tsvector('english', ?), 'A') setweight(to_tsvector('english', ?), 'A')
|| setweight(to_tsvector('english', ?), 'D') || setweight(to_tsvector('english', ?), 'D')
|| setweight(to_tsvector('english', COALESCE(?, '')), 'B') || setweight(to_tsvector('english', COALESCE(?, '')), 'B')
@ -71,21 +70,19 @@ class UserDirectoryStore(SQLBaseStore):
""" """
args = ( args = (
( (
user_id, room_id, p.display_name, p.avatar_url, user_id, get_localpart_from_id(user_id), get_domain_from_id(user_id),
get_localpart_from_id(user_id), get_domain_from_id(user_id), profile.display_name,
p.display_name,
) )
for user_id, p in users_with_profile.iteritems() for user_id, profile in users_with_profile.iteritems()
) )
elif isinstance(self.database_engine, Sqlite3Engine): elif isinstance(self.database_engine, Sqlite3Engine):
sql = """ sql = """
INSERT INTO user_directory INSERT INTO user_directory_search(user_id, value)
(user_id, room_id, display_name, avatar_url, value) VALUES (?,?)
VALUES (?,?,?,?,?)
""" """
args = ( args = (
( (
user_id, room_id, p.display_name, p.avatar_url, user_id,
"%s %s" % (user_id, p.display_name,) if p.display_name else user_id "%s %s" % (user_id, p.display_name,) if p.display_name else user_id
) )
for user_id, p in users_with_profile.iteritems() for user_id, p in users_with_profile.iteritems()
@ -96,6 +93,19 @@ class UserDirectoryStore(SQLBaseStore):
def _add_profiles_to_user_dir_txn(txn): def _add_profiles_to_user_dir_txn(txn):
txn.executemany(sql, args) txn.executemany(sql, args)
self._simple_insert_many_txn(
txn,
table="user_directory",
values=[
{
"user_id": user_id,
"room_id": room_id,
"display_name": profile.display_name,
"avatar_url": profile.avatar_url,
}
for user_id, profile in users_with_profile.iteritems()
]
)
for user_id in users_with_profile: for user_id in users_with_profile:
txn.call_after( txn.call_after(
self.get_user_in_directory.invalidate, (user_id,) self.get_user_in_directory.invalidate, (user_id,)
@ -117,12 +127,23 @@ class UserDirectoryStore(SQLBaseStore):
@defer.inlineCallbacks @defer.inlineCallbacks
def remove_from_user_dir(self, user_id): def remove_from_user_dir(self, user_id):
yield self._simple_delete( def _remove_from_user_dir_txn(txn):
table="user_directory", self._simple_delete_txn(
keyvalues={"user_id": user_id}, txn,
desc="remove_from_user_dir", table="user_directory",
keyvalues={"user_id": user_id},
)
self._simple_delete_txn(
txn,
table="user_directory_search",
keyvalues={"user_id": user_id},
)
txn.call_after(
self.get_user_in_directory.invalidate, (user_id,)
)
return self.runInteraction(
"remove_from_user_dir", _remove_from_user_dir_txn,
) )
self.get_user_in_directory.invalidate((user_id,))
def get_users_in_dir_due_to_room(self, room_id): def get_users_in_dir_due_to_room(self, room_id):
"""Get all user_ids that are in the room directory becuase they're """Get all user_ids that are in the room directory becuase they're
@ -150,6 +171,7 @@ class UserDirectoryStore(SQLBaseStore):
""" """
def _delete_all_from_user_dir_txn(txn): def _delete_all_from_user_dir_txn(txn):
txn.execute("DELETE FROM user_directory") txn.execute("DELETE FROM user_directory")
txn.execute("DELETE FROM user_directory_search")
txn.call_after(self.get_user_in_directory.invalidate_all) txn.call_after(self.get_user_in_directory.invalidate_all)
return self.runInteraction( return self.runInteraction(
"delete_all_from_user_dir", _delete_all_from_user_dir_txn "delete_all_from_user_dir", _delete_all_from_user_dir_txn
@ -225,7 +247,8 @@ class UserDirectoryStore(SQLBaseStore):
if isinstance(self.database_engine, PostgresEngine): if isinstance(self.database_engine, PostgresEngine):
sql = """ sql = """
SELECT user_id, display_name, avatar_url SELECT user_id, display_name, avatar_url
FROM user_directory FROM user_directory_search
INNER JOIN user_directory USING (user_id)
WHERE vector @@ plainto_tsquery('english', ?) WHERE vector @@ plainto_tsquery('english', ?)
ORDER BY ts_rank_cd(vector, plainto_tsquery('english', ?)) DESC ORDER BY ts_rank_cd(vector, plainto_tsquery('english', ?)) DESC
LIMIT ? LIMIT ?
@ -234,7 +257,8 @@ class UserDirectoryStore(SQLBaseStore):
elif isinstance(self.database_engine, Sqlite3Engine): elif isinstance(self.database_engine, Sqlite3Engine):
sql = """ sql = """
SELECT user_id, display_name, avatar_url SELECT user_id, display_name, avatar_url
FROM user_directory FROM user_directory_search
INNER JOIN user_directory USING (user_id)
WHERE value MATCH ? WHERE value MATCH ?
ORDER BY rank(matchinfo(user_directory)) DESC ORDER BY rank(matchinfo(user_directory)) DESC
LIMIT ? LIMIT ?