[MM-13500] Adds channel /search_group endpoint (#10805)

* [MM-13500] Adds channel /search_group endpoint

* Add LIMIT to the queries

* Fix i18n extract

* Fix tests

* Add a new endpoint to get profiles by group channel ids

* Rebase fix
Этот коммит содержится в:
Miguel de la Cruz
2019-06-22 00:14:21 +01:00
коммит произвёл GitHub
родитель 604e247135
Коммит 9e9b008f3d
15 изменённых файлов: 655 добавлений и 5 удалений

Просмотреть файл

@@ -1473,7 +1473,7 @@ func (s SqlChannelStore) GetMemberForPost(postId string, userId string) (*model.
Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
WHERE
ChannelMembers.UserId = :UserId
AND
AND
Posts.Id = :PostId`
if err := s.GetReplica().SelectOne(&dbMember, query, map[string]interface{}{"UserId": userId, "PostId": postId}); err != nil {
return nil, model.NewAppError("SqlChannelStore.GetMemberForPost", "store.sql_channel.get_member_for_post.app_error", nil, "postId="+postId+", err="+err.Error(), http.StatusInternalServerError)
@@ -2237,6 +2237,104 @@ func (s SqlChannelStore) performSearch(searchQuery string, term string, paramete
return &channels, nil
}
func (s SqlChannelStore) getSearchGroupChannelsQuery(userId, term string, isPostgreSQL bool) (string, map[string]interface{}) {
var query, baseLikeClause string
if isPostgreSQL {
baseLikeClause = "ARRAY_TO_STRING(ARRAY_AGG(u.Username), ', ') LIKE %s"
query = `
SELECT
*
FROM
Channels
WHERE
Id IN (
SELECT
cc.Id
FROM (
SELECT
c.Id
FROM
Channels c
JOIN
ChannelMembers cm on c.Id = cm.ChannelId
JOIN
Users u on u.Id = cm.UserId
WHERE
c.Type = 'G'
AND
u.Id = :UserId
GROUP BY
c.Id
) cc
JOIN
ChannelMembers cm on cc.Id = cm.ChannelId
JOIN
Users u on u.Id = cm.UserId
GROUP BY
cc.Id
HAVING
%s
LIMIT
` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT) + `
)`
} else {
baseLikeClause = "GROUP_CONCAT(u.Username SEPARATOR ', ') LIKE %s"
query = `
SELECT
cc.*
FROM (
SELECT
c.*
FROM
Channels c
JOIN
ChannelMembers cm on c.Id = cm.ChannelId
JOIN
Users u on u.Id = cm.UserId
WHERE
c.Type = 'G'
AND
u.Id = :UserId
GROUP BY
c.Id
) cc
JOIN
ChannelMembers cm on cc.Id = cm.ChannelId
JOIN
Users u on u.Id = cm.UserId
GROUP BY
cc.Id
HAVING
%s
LIMIT
` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT)
}
var likeClauses []string
args := map[string]interface{}{"UserId": userId}
terms := strings.Split(strings.ToLower(strings.Trim(term, " ")), " ")
for idx, term := range terms {
argName := fmt.Sprintf("Term%v", idx)
likeClauses = append(likeClauses, fmt.Sprintf(baseLikeClause, ":"+argName))
args[argName] = "%" + term + "%"
}
query = fmt.Sprintf(query, strings.Join(likeClauses, " AND "))
return query, args
}
func (s SqlChannelStore) SearchGroupChannels(userId, term string) (*model.ChannelList, *model.AppError) {
isPostgreSQL := s.DriverName() == model.DATABASE_DRIVER_POSTGRES
queryString, args := s.getSearchGroupChannelsQuery(userId, term, isPostgreSQL)
var groupChannels model.ChannelList
if _, err := s.GetReplica().Select(&groupChannels, queryString, args); err != nil {
return nil, model.NewAppError("SqlChannelStore.SearchGroupChannels", "store.sql_channel.search_group_channels.app_error", nil, "userId="+userId+", term="+term+", err="+err.Error(), http.StatusInternalServerError)
}
return &groupChannels, nil
}
func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) (*model.ChannelMembers, *model.AppError) {
var dbMembers channelMemberWithSchemeRolesList
props := make(map[string]interface{})

Просмотреть файл

@@ -20,10 +20,11 @@ import (
)
const (
PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins
PROFILE_BY_IDS_CACHE_SIZE = model.SESSION_CACHE_SIZE
PROFILE_BY_IDS_CACHE_SEC = 900 // 15 mins
PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins
PROFILE_BY_IDS_CACHE_SIZE = model.SESSION_CACHE_SIZE
PROFILE_BY_IDS_CACHE_SEC = 900 // 15 mins
MAX_GROUP_CHANNELS_FOR_PROFILES = 50
)
var (
@@ -920,6 +921,60 @@ func (us SqlUserStore) GetProfileByIds(userIds []string, allowFromCache bool, vi
})
}
type UserWithChannel struct {
model.User
ChannelId string
}
func (us SqlUserStore) GetProfileByGroupChannelIdsForUser(userId string, channelIds []string) (map[string][]*model.User, *model.AppError) {
if len(channelIds) > MAX_GROUP_CHANNELS_FOR_PROFILES {
channelIds = channelIds[0:MAX_GROUP_CHANNELS_FOR_PROFILES]
}
isMemberQuery := fmt.Sprintf(`
EXISTS(
SELECT
1
FROM
ChannelMembers
WHERE
UserId = '%s'
AND
ChannelId = cm.ChannelId
)`, userId)
query := us.getQueryBuilder().
Select("u.*, cm.ChannelId").
From("Users u").
Join("ChannelMembers cm ON u.Id = cm.UserId").
Join("Channels c ON cm.ChannelId = c.Id").
Where(sq.Eq{"c.Type": model.CHANNEL_GROUP, "cm.ChannelId": channelIds}).
Where(isMemberQuery).
Where(sq.NotEq{"u.Id": userId}).
OrderBy("u.Username ASC")
queryString, args, err := query.ToSql()
if err != nil {
return nil, model.NewAppError("SqlUserStore.GetProfileByGroupChannelIdsForUser", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
}
usersWithChannel := []*UserWithChannel{}
if _, err := us.GetReplica().Select(&usersWithChannel, queryString, args...); err != nil {
return nil, model.NewAppError("SqlUserStore.GetProfileByGroupChannelIdsForUser", "store.sql_user.get_profile_by_group_channel_ids_for_user.app_error", nil, err.Error(), http.StatusInternalServerError)
}
usersByChannelId := map[string][]*model.User{}
for _, user := range usersWithChannel {
if val, ok := usersByChannelId[user.ChannelId]; ok {
usersByChannelId[user.ChannelId] = append(val, &user.User)
} else {
usersByChannelId[user.ChannelId] = []*model.User{&user.User}
}
}
return usersByChannelId, nil
}
func (us SqlUserStore) GetSystemAdminProfiles() store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
query := us.usersQuery.