manually de-duplicate result set for SearchBoardsForUserInTeam since adding to the query increased cost by 15X (#4232)

This commit is contained in:
Doug Lauder 2022-11-22 12:53:08 -05:00 committed by GitHub
parent aca0107b34
commit 20d8d7a0ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -673,7 +673,6 @@ func (s *MattermostAuthLayer) baseUserQuery(showEmail, showName bool) sq.SelectB
func (s *MattermostAuthLayer) SearchBoardsForUser(term, userID string, includePublicBoards bool) ([]*model.Board, error) { func (s *MattermostAuthLayer) SearchBoardsForUser(term, userID string, includePublicBoards bool) ([]*model.Board, error) {
query := s.getQueryBuilder(). query := s.getQueryBuilder().
Select(boardFields("b.")...). Select(boardFields("b.")...).
Distinct().
From(s.tablePrefix + "boards as b"). From(s.tablePrefix + "boards as b").
LeftJoin(s.tablePrefix + "board_members as bm on b.id=bm.board_id"). LeftJoin(s.tablePrefix + "board_members as bm on b.id=bm.board_id").
LeftJoin("TeamMembers as tm on tm.teamid=b.team_id"). LeftJoin("TeamMembers as tm on tm.teamid=b.team_id").
@ -739,7 +738,9 @@ func (s *MattermostAuthLayer) SearchBoardsForUser(term, userID string, includePu
} }
defer s.CloseRows(rows) defer s.CloseRows(rows)
return s.boardsFromRows(rows) // de-duplicate manually since adding `distinct` to the query increased cost by 15X.
// the result set for any user should be reasonably small as its based on their channel membership.
return s.boardsFromRows(rows, true)
} }
// searchBoardsForUserInTeam returns all boards that match with the // searchBoardsForUserInTeam returns all boards that match with the
@ -749,7 +750,6 @@ func (s *MattermostAuthLayer) SearchBoardsForUser(term, userID string, includePu
func (s *MattermostAuthLayer) SearchBoardsForUserInTeam(teamID, term, userID string) ([]*model.Board, error) { func (s *MattermostAuthLayer) SearchBoardsForUserInTeam(teamID, term, userID string) ([]*model.Board, error) {
query := s.getQueryBuilder(). query := s.getQueryBuilder().
Select(boardFields("b.")...). Select(boardFields("b.")...).
Distinct().
From(s.tablePrefix + "boards as b"). From(s.tablePrefix + "boards as b").
LeftJoin(s.tablePrefix + "board_members as bm on b.id=bm.board_id"). LeftJoin(s.tablePrefix + "board_members as bm on b.id=bm.board_id").
LeftJoin("ChannelMembers as cm on cm.channelId=b.channel_id"). LeftJoin("ChannelMembers as cm on cm.channelId=b.channel_id").
@ -784,11 +784,14 @@ func (s *MattermostAuthLayer) SearchBoardsForUserInTeam(teamID, term, userID str
} }
defer s.CloseRows(rows) defer s.CloseRows(rows)
return s.boardsFromRows(rows) // de-duplicate manually since adding `distinct` to the query increased cost by 15X.
// the result set for any user should be reasonably small as its based on their channel membership.
return s.boardsFromRows(rows, true)
} }
func (s *MattermostAuthLayer) boardsFromRows(rows *sql.Rows) ([]*model.Board, error) { func (s *MattermostAuthLayer) boardsFromRows(rows *sql.Rows, removeDuplicates bool) ([]*model.Board, error) {
boards := []*model.Board{} boards := []*model.Board{}
idMap := make(map[string]struct{})
for rows.Next() { for rows.Next() {
var board model.Board var board model.Board
@ -820,6 +823,14 @@ func (s *MattermostAuthLayer) boardsFromRows(rows *sql.Rows) ([]*model.Board, er
return nil, err return nil, err
} }
if removeDuplicates {
if _, ok := idMap[board.ID]; ok {
continue
} else {
idMap[board.ID] = struct{}{}
}
}
err = json.Unmarshal(propertiesBytes, &board.Properties) err = json.Unmarshal(propertiesBytes, &board.Properties)
if err != nil { if err != nil {
s.logger.Error("board properties unmarshal error", mlog.Err(err)) s.logger.Error("board properties unmarshal error", mlog.Err(err))